我知道如何解析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浏览器中不可用。


当前回答

为了完整起见,这里是我最终得到的一个简单的一行程序(我不需要检查非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 }'));

其他回答

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

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

一个假设是,您定义了一个特殊的字段,该字段在您想要自动应用它的类型的每个对象中指示它的类型。__type在例子中)。

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);
}

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

你可以改变这个

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

这个

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

您想添加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 title, var author等,并向它们添加getter来完成UML定义。

一篇我觉得很有用的博客文章: 理解JavaScript原型

你可以扰乱对象的__proto__属性。

var fooJSON = jQuery.parseJSON({"a":4, "b": 3});
fooJSON.__proto__ = Foo.prototype;

这允许fooJSON继承Foo原型。

我不认为这在IE中工作,尽管…至少从我所读到的来看是这样。