将 JSON 对象映射到 Javascript 对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8783327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mapping JSON Objects to Javascript Objects
提问by ryandlf
When using AJAX, I tend to pass objects from my server to Javascript in the form of JSON objects (aka Javascript). Certain functions within my Javascript rely on the specific type of object I am using. For instance, lets use a phone number for example. I have a constructor:
使用 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;
}
Which I use when creating a phone number object in my Javascript. In some situations I don't create the object in JS, I get the object from the server so it comes in the form of a generic object with the exact same fields. So when my code relies on the specific type by using something such as this:
我在我的 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]);
}
In this situation, I check the name of the objects constructor and set certain variables based on that name. If the object I check the name on is a JSON from the server, it simply gives me a generic "Object" response and thus the code does not work. I get around this by using a mapping function for each object such as:
在这种情况下,我检查对象构造函数的名称并根据该名称设置某些变量。如果我检查名称的对象是来自服务器的 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;
}
This works just fine, but to me seems a little redundant. Is this the best way to solve the JSON Object problem, or is there a better solution? I understand this is more of a "Am I doing this the best way possible" type of question, but I repeat this type of logic CONSTANTLY in my Javascript code and I figure I might as well get another opinion or two on whether or not its the proper way to do this before I have to spend hour upon hour fixing it in the future.
这工作得很好,但对我来说似乎有点多余。这是解决 JSON 对象问题的最佳方法,还是有更好的解决方案?我明白这更像是“我是否以最好的方式这样做”类型的问题,但我在我的 Javascript 代码中不断重复这种类型的逻辑,我想我可能会得到另外一两个意见在我必须花一个小时一个小时地修复它之前,正确的方法来做到这一点。
EDIT: I ended up accepting a jQuery solution because I happen to use jQuery in my project. There are however multiple solutions that also worked for me before I found the jQuery option. They just weren't quite as clean and efficient.
编辑:我最终接受了 jQuery 解决方案,因为我碰巧在我的项目中使用了 jQuery。然而,在我找到 jQuery 选项之前,有多种解决方案也对我有用。他们只是没有那么干净和高效。
回答by ThiefMaster
The following requires you to have the same properties in your object and your JSON object.
以下要求您的对象和 JSON 对象具有相同的属性。
var phoneNumber = $.extend(new PhoneNumber(), yourJSONObject);
This basically creates a new PhoneNumber object and then copies all properties from your JSON object onto it. The $.extend()
method is from jQuery, but you could also use as similar method from e.g. Underscore.js or one of the other js libraries/frameworks.
这基本上创建了一个新的 PhoneNumber 对象,然后将所有属性从 JSON 对象复制到它上面。该$.extend()
方法来自 jQuery,但您也可以使用来自例如 Underscore.js 或其他 js 库/框架之一的类似方法。
回答by Levi
This similar question has a lot of interesting answers:
这个类似的问题有很多有趣的答案:
Parse JSON String into a Particular Object Prototype in JavaScript
将 JSON 字符串解析为 JavaScript 中的特定对象原型
Based off the poster's own answer, I think this would be an effective solution for you:
根据海报自己的回答,我认为这对您来说是一个有效的解决方案:
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;
}
You will need to add objectType to the JSON objects you are receiving to define the javascript class you want to instantiate. Then when you call this function, it will cast the object to that type and copy the data over (including the variable 'objectType').
您需要将 objectType 添加到您收到的 JSON 对象中,以定义要实例化的 javascript 类。然后,当您调用此函数时,它会将对象强制转换为该类型并复制数据(包括变量“objectType”)。
Using your phone number example, your code would look like this:
使用您的电话号码示例,您的代码如下所示:
// 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);
回答by Amadan
AFAIK, in everything that is not IE, you can do this:
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();
Unfortunately, IE does not support the __proto__
accessor, so what you would need to do is first create an empty instance of your object, then just copy everything over:
不幸的是,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();
Both of these approaches are quite a bit more generic than your mapWhatever
functions, keeping it DRY.
这两种方法都比你的mapWhatever
函数更通用,保持 DRY。
回答by Adam Rackis
If not supporting older browsers is ok, You can use Object.create
to do the mapping for you. (dropping the shim—at least the shim at MDN—in will notfix older browsers, since that shim does not accept the second parameter.)
如果不支持旧浏览器也可以,您可以使用为您Object.create
做映射。(删除 shim——至少是 MDN 上的 shim——不会修复旧浏览器,因为该 shim 不接受第二个参数。)
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 ...