将JSON字符串解析为JavaScript中的特定对象原型

将JSON字符串解析为JavaScript中的特定对象原型,javascript,json,parsing,object,prototype,Javascript,Json,Parsing,Object,Prototype,我知道如何解析JSON字符串并将其转换为JavaScript对象。 您可以在现代浏览器(和IE9+)中使用JSON.parse() 这很好,但我如何将该JavaScript对象转换为特定的JavaScript对象(即使用特定的原型) 例如,假设您有: function Foo() { this.a = 3; this.b = 2; this.test = function() {return this.a*this.b;}; } var fooObj = new Foo();

我知道如何解析JSON字符串并将其转换为JavaScript对象。 您可以在现代浏览器(和IE9+)中使用
JSON.parse()

这很好,但我如何将该JavaScript对象转换为特定的JavaScript对象(即使用特定的原型)

例如,假设您有:

function Foo()
{
   this.a = 3;
   this.b = 2;
   this.test = function() {return this.a*this.b;};
}
var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6
var fooJSON = JSON.parse({"a":4, "b": 3});
//Something to convert fooJSON into a Foo Object
//....... (this is what I am missing)
alert(fooJSON.test() ); //Prints 12
同样,我并不想知道如何将JSON字符串转换为通用JavaScript对象。我想知道如何将JSON字符串转换为“Foo”对象。也就是说,我的对象现在应该有一个函数“test”和属性“a”和“b”

更新 在做了一些研究之后,我想到了这个

Object.cast = function cast(rawObj, constructor)
{
    var obj = new constructor();
    for(var i in rawObj)
        obj[i] = rawObj[i];
    return obj;
}
var fooJSON = Object.cast({"a":4, "b": 3}, Foo);
这样行吗

2017年5月更新:执行此操作的“现代”方式是通过,但此功能在IE 11或更旧的Android浏览器中不可用。

请参见下面的示例(此示例使用本机JSON对象)。我的更改以大写字母表示:

function Foo(obj) // CONSTRUCTOR CAN BE OVERLOADED WITH AN OBJECT
{
    this.a = 3;
    this.b = 2;
    this.test = function() {return this.a*this.b;};

    // IF AN OBJECT WAS PASSED THEN INITIALISE PROPERTIES FROM THAT OBJECT
    for (var prop in obj) this[prop] = obj[prop];
}

var fooObj = new Foo();
alert(fooObj.test() ); //Prints 6

// INITIALISE A NEW FOO AND PASS THE PARSED JSON OBJECT TO IT
var fooJSON = new Foo(JSON.parse('{"a":4,"b":3}'));

alert(fooJSON.test() ); //Prints 12

我发现一篇有用的博客文章:

您可能会弄乱对象的_proto___)属性

var fooJSON = jQuery.parseJSON({"a":4, "b": 3});
fooJSON.__proto__ = Foo.prototype;
这允许fooJSON继承Foo原型


我认为这在IE中不起作用,不过。。。至少从我所读到的来看。

您想添加JSON序列化/反序列化功能,对吗?然后看看这个:

您希望实现以下目标:

toJson()是一个普通方法。
fromJson()是一个静态方法

实施

var Book = function (title, author, isbn, price, stock){
    this.title = title;
    this.author = author;
    this.isbn = isbn;
    this.price = price;
    this.stock = stock;

    this.toJson = function (){
        return ("{" +
            "\"title\":\"" + this.title + "\"," +
            "\"author\":\"" + this.author + "\"," +
            "\"isbn\":\"" + this.isbn + "\"," +
            "\"price\":" + this.price + "," +
            "\"stock\":" + this.stock +
        "}");
    };
};

Book.fromJson = function (json){
    var obj = JSON.parse (json);
    return new Book (obj.title, obj.author, obj.isbn, obj.price, obj.stock);
};
var book = new Book ("t", "a", "i", 10, 10);
var json = book.toJson ();
alert (json); //prints: {"title":"t","author":"a","isbn":"i","price":10,"stock":10}

var book = Book.fromJson (json);
alert (book.title); //prints: t
用法

var Book = function (title, author, isbn, price, stock){
    this.title = title;
    this.author = author;
    this.isbn = isbn;
    this.price = price;
    this.stock = stock;

    this.toJson = function (){
        return ("{" +
            "\"title\":\"" + this.title + "\"," +
            "\"author\":\"" + this.author + "\"," +
            "\"isbn\":\"" + this.isbn + "\"," +
            "\"price\":" + this.price + "," +
            "\"stock\":" + this.stock +
        "}");
    };
};

Book.fromJson = function (json){
    var obj = JSON.parse (json);
    return new Book (obj.title, obj.author, obj.isbn, obj.price, obj.stock);
};
var book = new Book ("t", "a", "i", 10, 10);
var json = book.toJson ();
alert (json); //prints: {"title":"t","author":"a","isbn":"i","price":10,"stock":10}

var book = Book.fromJson (json);
alert (book.title); //prints: t

注意:如果需要,您可以通过
var title
var author
等更改所有属性定义,如
this.title
this.author
等,并向其添加getter以完成UML定义。

然而,这在技术上不是您想要的,如果事先知道要处理的对象类型,可以使用已知对象原型的调用/应用方法

你可以改变这个

alert(fooJSON.test() ); //Prints 12
对此

alert(Foo.prototype.test.call(fooJSON); //Prints 12

Olivers的回答很清楚,但如果你想在angular js中寻找解决方案,我已经编写了一个很好的模块angular jsClass,它可以很容易地实现这一点,当你瞄准一个大项目,但说开发人员面临的问题正是BMiner所说的,如何将json序列化为原型或构造函数表示法对象

var jone = new Student();
jone.populate(jsonString); // populate Student class with Json string
console.log(jone.getName()); // Student Object is ready to use

为了完整起见,这里有一个简单的一行代码,我最后使用了它(我不需要检查非Foo属性):


可以使用另一种方法。作为第一个参数,传递原型,对于第二个参数,传递属性名称映射到描述符:

函数SomeConstructor(){
};
SomeConstructor.prototype={
doStuff:function(){
日志(“一些东西”);
}
};
var jsonText='{“text”:“hello wrold”}';
var反序列化=JSON.parse(jsonText);
//这将构建一个属性到描述符映射
//Object.create的#2参数必需
变量描述符=Object.keys(反序列化)
.reduce(函数(结果、属性){
结果[属性]=Object.getOwnPropertyDescriptor(反序列化,属性);
}, {});

var obj=Object.create(SomeConstructor.prototype,描述符)当前的答案包含大量手动或库代码。这是没有必要的

  • 使用
    JSON.parse('{“a”:1}')
    创建普通对象

  • 使用标准化功能之一设置原型:

    • Object.assign(新的Foo,{a:1})
    • Object.setPrototypeOf({a:1},Foo.prototype)

  • 我是否在问题中遗漏了什么,或者为什么自2011年以来就没有人提到这个参数

    以下是解决方案的简化代码:

    PS:您的问题令人困惑:>>这很好,但我如何将该JavaScript对象转换为特定的JavaScript对象(即使用特定的原型)?
    与标题相矛盾,您在标题中询问JSON解析,但是引用的段落询问了关于JS运行时对象原型替换的问题。

    我将能够找到的解决方案组合起来,并将其编译成一个通用的解决方案,该解决方案可以递归地自动解析自定义对象及其所有字段,以便在反序列化后使用原型方法

    一个假设是,您定义了一个特殊字段,该字段指示要自动应用其类型的每个对象中的类型(
    this.\u type

    类型分配函数(它递归地将类型分配给任何嵌套对象;它还遍历数组以查找任何合适的对象):

    函数赋值类型(对象){
    if(object&&typeof(object)=='object'&&window[object.\uu type]){
    object=赋值类型递归(object.\u类型,object);
    }
    返回对象;
    }
    函数赋值类型递归(类型,对象){
    for(对象中的变量键){
    if(object.hasOwnProperty(key)){
    var obj=对象[键];
    if(数组isArray(obj)){
    对于(变量i=0;i
    我创建了一个名为的包。它支持(循环)引用和类实例


    您必须在类中定义两个新方法(
    toDry
    在原型上,将
    unDry
    作为静态方法),注册该类(
    Dry.registerClass
    ),然后就可以开始了。

    我喜欢向构造函数添加可选参数并调用
    
    
    function Msg(data) {
        //... your init code
        this.data = data //can be another object or an array of objects of custom types. 
                         //If those objects defines `this.__type', their types will be assigned automatically as well
        this.__type = "Msg"; // <- store the object's type to assign it automatically
    }
    
    Msg.prototype = {
        createErrorMsg: function(errorMsg){
            return new Msg(0, null, errorMsg)
        },
        isSuccess: function(){
            return this.errorMsg == null;
        }
    }
    
    var responseMsg = //json string of Msg object received;
    responseMsg = assignType(responseMsg);
    
    if(responseMsg.isSuccess()){ // isSuccess() is now available
          //furhter logic
          //...
    }
    
    function assignType(object){
        if(object && typeof(object) === 'object' && window[object.__type]) {
            object = assignTypeRecursion(object.__type, object);
        }
        return object;
    }
    
    function assignTypeRecursion(type, object){
        for (var key in object) {
            if (object.hasOwnProperty(key)) {
                var obj = object[key];
                if(Array.isArray(obj)){
                     for(var i = 0; i < obj.length; ++i){
                         var arrItem = obj[i];
                         if(arrItem && typeof(arrItem) === 'object' && window[arrItem.__type]) {
                             obj[i] = assignTypeRecursion(arrItem.__type, arrItem);
                         }
                     }
                } else  if(obj && typeof(obj) === 'object' && window[obj.__type]) {
                    object[key] = assignTypeRecursion(obj.__type, obj);
                }
            }
        }
        return Object.assign(new window[type](), object);
    }
    
    constructor(obj) {
        if (obj != null) {
            Object.assign(this, obj);
            if (this.ingredients != null) {
                this.ingredients = this.ingredients.map(x => new Ingredient(x));
            }
        }
    }