我知道如何解析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月更新:“现代”的方式是通过对象。但该功能在ie11或更老的Android浏览器中不可用。


当前回答

获得理想效果的一个非常简单的方法是在生成json字符串时添加一个type属性,并在解析字符串时使用该字符串来生成对象:

    serialize = function(pObject) {
        return JSON.stringify(pObject, (key, value) => {
            if (typeof(value) == "object") {
                value._type = value.constructor.name;
            }
            return value;
        });
    }
    
    deSerialize = function(pJsonString) {
        return JSON.parse(pJsonString, (key, value) => {
            if (typeof(value) == "object" && value._type) {
                value = Object.assign(eval('new ' + value._type + '()'), value);
                delete value._type;
            }
            return value;
        });
    }

这里有一个使用的小例子:

    class TextBuffer {
        constructor() {
            this.text = "";
        }
        
        getText = function() {
            return this.text;
        }
        
        setText = function(pText) {
            this.text = pText;
        }
    }
    
    let textBuffer = new TextBuffer();
    textBuffer.setText("Hallo");
    console.log(textBuffer.getText()); // "Hallo"
    
    let newTextBuffer = deSerialize(serialize(textBuffer));
    console.log(newTextBuffer.getText()); // "Hallo"

其他回答

oliver的答案非常清楚,但如果你想在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

https://github.com/imalhasaranga/Angular-JSClass

为了完整起见,这里是我最终得到的一个简单的一行程序(我不需要检查非foo属性):

var Foo = function(){ this.bar = 1; };

// angular version
var foo = angular.extend(new Foo(), angular.fromJson('{ "bar" : 2 }'));

// jquery version
var foo = jQuery.extend(new Foo(), jQuery.parseJSON('{ "bar" : 3 }'));

然而,从技术上讲,这并不是你想要的,如果你事先知道你想要处理的对象类型,你可以使用已知对象原型的call/apply方法。

你可以改变这个

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

这个

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

获得理想效果的一个非常简单的方法是在生成json字符串时添加一个type属性,并在解析字符串时使用该字符串来生成对象:

    serialize = function(pObject) {
        return JSON.stringify(pObject, (key, value) => {
            if (typeof(value) == "object") {
                value._type = value.constructor.name;
            }
            return value;
        });
    }
    
    deSerialize = function(pJsonString) {
        return JSON.parse(pJsonString, (key, value) => {
            if (typeof(value) == "object" && value._type) {
                value = Object.assign(eval('new ' + value._type + '()'), value);
                delete value._type;
            }
            return value;
        });
    }

这里有一个使用的小例子:

    class TextBuffer {
        constructor() {
            this.text = "";
        }
        
        getText = function() {
            return this.text;
        }
        
        setText = function(pText) {
            this.text = pText;
        }
    }
    
    let textBuffer = new TextBuffer();
    textBuffer.setText("Hallo");
    console.log(textBuffer.getText()); // "Hallo"
    
    let newTextBuffer = deSerialize(serialize(textBuffer));
    console.log(newTextBuffer.getText()); // "Hallo"

我喜欢在构造函数中添加可选参数并调用Object。赋值(this, obj),然后处理对象或对象数组本身的任何属性:

constructor(obj) {
    if (obj != null) {
        Object.assign(this, obj);
        if (this.ingredients != null) {
            this.ingredients = this.ingredients.map(x => new Ingredient(x));
        }
    }
}