javascript JSON直接将对象属性解析为int

时间:2012-05-12 12:45:45

标签: javascript

我有一些使用本机浏览器实现从json解析的对象。一些对象的属性是数字。目前,数字是从json解析为字符串,我使用parseInt将字符串转换为我需要的int。

问题是我有23个对象,我总共有大约80个属性,我正在解析这样的内容:

if (TheObject && TheObject.TheProperty) {
   TheObject.TheProperty = parseInt(TheObject.TheProperty, 10);
}

有许多代码看起来非常相似。是否有一种方法可以使用原型或其他东西来改变JSON.parse函数的工作方式,这样每次解析器运行时都会检查字符串属性是否实际上是一个int,如果是这样就直接将它转换成这样?

感谢。

5 个答案:

答案 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
    }
}

如果您的属性是双引号,那么它是一个字符串,否则它是一个数字,布尔值(truefalse值),null或只是导致解析错误的东西。

请参阅http://json.org/

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

Live example | source

或者,如果属性名称不够独特(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']);