If your data source can't be fixed (numbers should be passed as numbers, not as strings), you can pass JSON.parse a "reviver" function, which will receive each item as it's being processed. This gives you the option of transforming it:
// 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
Or if the property names are not sufficiently unique (TheProperty doesn't always need handling, just when it's a property of TheObject), you can do this as a two-level check:
// 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 are called inside-out, so the properties will be on the object by the time you see the object's key; that's why we update them in place.)
You get the idea, there's a lot you can do with reviver functions.
Side note: parseInt, which I've used above, is fairly forgiving — possibly more forgiving than you want. For instance:
var a = parseInt('1a', 10); // 1, instead of NaN
If you're okay with strings like "0x10" being treated as hex, then:
var a = Number(str);
...which will give you NaN for invalid number strings (Number("1a") is NaN). Since JSON isn't meant to have hex numbers, if you're sure the broken data source won't encode them as hex, you're golden.
Otherwise, if you need decimal but you want to be strict, you'll need to do a regex on the string to make sure it matches the pattern for a valid decimal number (which is fairly complex, if you want to support all the stuff JavaScript numeric literals support).
parseInt('1a', 10);returns1? But anyway, even if property looks like a number - it doesn't mean it is numericJSON.parsecan handle this natively, but it would be better to send them as numbers in the first place. Is this out of the question?