我有一些使用本机浏览器实现从json解析的对象。一些对象的属性是数字。目前,数字是从json解析为字符串,我使用parseInt将字符串转换为我需要的int。
问题是我有23个对象,我总共有大约80个属性,我正在解析这样的内容:
if (TheObject && TheObject.TheProperty) {
TheObject.TheProperty = parseInt(TheObject.TheProperty, 10);
}
有许多代码看起来非常相似。是否有一种方法可以使用原型或其他东西来改变JSON.parse函数的工作方式,这样每次解析器运行时都会检查字符串属性是否实际上是一个int,如果是这样就直接将它转换成这样?
感谢。
答案 0 :(得分:10)
JSON.parse
以函数的形式接受第二个参数,可以进行一些后期处理。
JSON.parse('{"p": "5"}', function(k, v) {
return (typeof v === "object" || isNaN(v)) ? v : parseInt(v, 10);
});
我不想处理所有数字字符串,然后创建一个你想要的属性的查找表。
var props = {"p":1, "some_prop":1, "another_prop":1};
JSON.parse('{"p": "5"}', function(k, v) {
return props.hasOwnProperty(k) ? parseInt(v, 10) : v;
});
答案 1 :(得分:8)
JSON可以处理如下数字:
{
"TheObject":{
"TheProperty":5
}
}
如果您的属性是双引号,那么它是一个字符串,否则它是一个数字,布尔值(true
和false
值),null
或只是导致解析错误的东西。
答案 2 :(得分:2)
我认为您无法修改解析器,但是不使用许多类似的代码行,而是使用属性数组并使用[]
表示法在{parseInt()
符号中访问它们。 1}}他们。当然,如果您可以访问生成JSON的代码,则可以更容易地将其更改为输出正确的未引用的内容。
// Array of properties you want to parse out
var parseUs = ['prop1','prop2','prop3','prop4'];
// Array of objects you need to parse them in
var objs = [obj1, obj2, obj3];
// Iterate over the objects
for (var i=0; i<objs.length; i++) {
// And over the properties array
for (var j=0; j<parseUs.length; j++) {
// Parse out the int value if the object has the property
if (objs[i].hasOwnProperty(parseUs[j]) {
objs[i][parseUs[j]] = parseInt(parseUs[j], 10);
}
}
}
注意:如果对象共享所有属性中不是int值的属性名称,则无效。如果是这种情况,则需要修改它以使用每个对象的属性数组。
答案 3 :(得分:2)
如果您的数据源无法修复(数字应作为数字而不是字符串传递)you can pass JSON.parse
a "reviver" function,它将在处理时收到每个项目。这使您可以选择转换它:
// Create this once
var propsToConvert = {
TheProperty: 1,
TheOtherProperty: 1,
YetAnotherProperty: 1,
// ...and so on...
};
// Use it each time you parse
var obj = JSON.parse(str, function(key, value) {
if (propsToConvert.hasOwnProperty(key)) {
return parseInt(value, 10);
}
return value;
});
或者,如果属性名称不够独特(TheProperty
总是需要处理,只要它是TheObject
的属性),您可以这样做两级检查:
// Define the object names and their property names (once)
var propsToConvert = {
TheObject: {
TheProperty: 1,
TheOtherProperty: 1,
YetAnotherProperty: 1,
// ...and so on...
},
AnotherObject: {
// Other properties...
}
};
// Use it each time you parse
var obj = JSON.parse(str, function(key, value) {
var name, props;
if (typeof value === "object") {
props = propsToConvert[key];
if (props) {
for (name in props) {
value[name] = parseInt(value[name], 10);
}
}
}
});
(Revivers被称为内向外,因此当您看到对象的键时,属性将出现在对象上;这就是我们更新它们的原因。)
你明白了,你可以用reviver函数做 lot 。
旁注:parseInt
,我在上面使用过,相当宽容 - 可能比你想要的更宽容。例如:
var a = parseInt('1a', 10); // 1, instead of NaN
如果你可以将"0x10"
之类的字符串视为十六进制,那么:
var a = Number(str);
...这会为NaN
提供无效的数字字符串(Number("1a")
为NaN
)。由于JSON不具有十六进制数字,如果您确定损坏的数据源不会将它们编码为十六进制,那么您就是黄金。
否则,如果你需要小数但你想要严格,你需要对字符串做一个正则表达式,以确保它匹配有效十进制数的模式(如果你想支持,这是相当复杂的所有的东西都是JavaScript数字文字支持的。)
答案 4 :(得分:1)
@kbec给出了正确的答案。如果您无法控制数据源,则可以使用以下内容:
function intify(obj, fields) {
if (typeof(obj) == "undefined") return;
var numFields = fields.length;
for (var i = 0; i < numFields; i++) {
var field = fields[i];
if (typeof(obj[field]) != "undefined") {
obj[field] = parseInt(obj[field], 10);
}
}
return obj;
}
intify(obj, ['foo', 'bar']);
intify(obj.baz, ['boo']);