将JSON对象映射到Javascript对象

时间:2012-01-09 02:30:52

标签: javascript json

使用AJAX时,我倾向于以JSON对象(又称Javascript)的形式将对象从我的服务器传递给Javascript。我的Javascript中的某些函数依赖于我正在使用的特定类型的对象。例如,让我们使用电话号码。我有一个构造函数:

function PhoneNumber(number, type, isPrimary, contactId, id, className) {
    this.number = number;
    this.type = type;
    this.isPrimary = isPrimary;
    this.contactId = contactId;
    this.id = id;
    this.className = className;
}

我在Javascript中创建电话号码对象时使用的。在某些情况下,我不在JS中创建对象,我从服务器获取对象,因此它以具有完全相同字段的通用对象的形式出现。因此,当我的代码依赖于特定类型时,可以使用以下内容:

var objType = objArray[i].constructor.name;
var mappedObj;

switch(objType) {
    case 'PhoneNumber':
        currentArray = currentArray.phone;
        //Convert response to javascript object.
        mappedObj = mapPhone(jsonResponse[i]);
        break;
    case 'Email':
        currentArray = currentArray.email;
        mappedObj = mapEmail(jsonResponse[i]);
        break;
    case 'Address':
        currentArray = currentArray.address;
        mappedObj = mapAddress(jsonResponse[i]);
        break;
    case 'Website':
        currentArray = currentArray.website;
        mappedObj = mapWebsite(jsonResponse[i]);
}

在这种情况下,我检查对象构造函数的名称,并根据该名称设置某些变量。如果我检查名称的对象是来自服务器的JSON,它只是给我一个通用的“对象”响应,因此代码不起作用。我通过为每个对象使用映射函数来解决这个问题,例如:

function mapPhone(phoneObj) {
    var id = phoneObj.id;
    var contactId = phoneObj.contactId;
    var number = phoneObj.number;
    var type = phoneObj.type;
    var primary = phoneObj.isPrimary;
    var className = phoneObj.className;
    var phoneNumber = new PhoneNumber(number, type, primary, contactId, id, className);
    return phoneNumber;
}

这很好用,但对我来说似乎有点多余。这是解决JSON对象问题的最佳方法,还是有更好的解决方案?我理解这更像是“我这样做是最好的方式”类型的问题,但我在我的Javascript代码中不断重复这种类型的逻辑,我想我也可能会得到另一个或两个关于它的意见在我将来必须花费一小时的时间来修复它之前,这是正确的方法。

编辑:我最终接受了jQuery解决方案,因为我碰巧在我的项目中使用了jQuery。然而,在找到jQuery选项之前,有多个解决方案对我有用。他们只是不那么干净和高效。

4 个答案:

答案 0 :(得分:25)

以下要求您在对象和JSON对象中具有相同的属性。

var phoneNumber = $.extend(new PhoneNumber(), yourJSONObject);

这基本上创建了一个新的PhoneNumber对象,然后将JSON对象中的所有属性复制到它上面。 $.extend()方法来自jQuery,但您也可以使用类似于Underscore.js或其他js库/框架之一。

答案 1 :(得分:3)

这个类似的问题有很多有趣的答案:

Parse JSON String into a Particular Object Prototype in JavaScript

根据海报自己的答案,我认为这对您来说是一个有效的解决方案:

function recastJSON(jsonObject) {
    // return generic object if objectType is not specified
    if (!jsonObject.objectType)
        return jsonObject;

    // otherwise create a new object of type specified
    var obj = eval('new '+jsonObject.objectType+'()');
    for(var i in jsonObject)
        obj[i] = jsonObject[i];
    return obj;
}

您需要将objectType添加到您要接收的JSON对象,以定义要实例化的javascript类。然后,当您调用此函数时,它会将对象强制转换为该类型并复制数据(包括变量'objectType')。

使用您的电话号码示例,您的代码如下所示:

// generic object from JSON
var genericObject = {objectType:'PhoneNumber', number:'555-555-5555', type:'home', primary:true, contactId:123, id:1234, className:'stdPhone'};
var phoneObject = recastJSON(genericObject);

答案 2 :(得分:2)

AFAIK,在所有不是IE的东西中,你可以这样做:

// define a class
var Foo = function(name) {
  this.name = name;
}
// make a method
Foo.prototype.shout = function() {
  return "I am " + this.name;
}
// make a simple object from JSON:
var x = JSON.parse('{ "name": "Jason" }');
// force its class to be Foo
x.__proto__ = Foo.prototype;
// the method works
x.shout();

不幸的是,IE不支持__proto__访问器,所以你需要做的是首先创建一个对象的空实例,然后只复制所有内容:

// make a simple object from JSON:
var x = JSON.parse('{ "name": "Jason" }');
// make an empty Foo
var y = Object.create(Foo.prototype);
// copy stuff over
for (a in x) {
  y[a] = x[a];
}
y.shout();

这两种方法都比你的mapWhatever函数更通用,保持干燥。

答案 3 :(得分:1)

如果不支持旧版浏览器,则可以使用Object.create为您执行映射。 (删除垫片 - 至少垫片在MDN-in将修复旧浏览器,因为该垫片不接受第二个参数。)

DEMO

function makeThisExtend(obj, CtorFunc) {
    for (var k in obj)
        if ({}.hasOwnProperty.call(obj, k))
            obj[k] = { value: obj[k] };

    return Object.create(CtorFunc.prototype, obj);
}

var objFromServer = { Number: "123", id: 5 };
objFromServer = makeThisExtend(objFromServer, PhoneNumber);


alert(objFromServer.Number + " " + objFromServer.id); //123 5
alert(objFromServer.constructor); //function PhoneNumber ...
相关问题