Reputation: 362
I have the following text:
{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}
I need to match and place quotes around the numbers in the array "values" so its result should be:
{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": ["3.523422","0","-323123123","3.423","9223372036854775807","0","test 123.32","0","0","","0","0"]}}
The numbers can be with float point, negative and normal.
Upvotes: 1
Views: 1509
Reputation: 29112
If you really can't change the original JSON to use strings for numbers that aren't within the range supported by JS then you could use something like this:
var json = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0, "test \\u0022 123", "test \\" 123"]}}';
var inString = false;
var inNumber = false;
var out = '';
for (var index = 0, len = json.length ; index < len ; ++index) {
var chr = json.charAt(index);
switch (chr) {
case '"':
inString = !inString;
break;
case '\\':
out += chr + json.charAt(index + 1);
++index;
continue;
case '-':
case '.':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (!inString && !inNumber) {
out += '"';
inNumber = true;
}
break;
default:
if (inNumber) {
inNumber = false;
out += '"';
}
}
out += chr;
}
console.log(out);
Handling the numbers in strings is too tricky using a RegExp so I haven't even tried. I've assumed the JSON is valid... my crude parser won't cope at all well if it isn't. I've also ignored the 7e5
notation for numbers, that would need a bit of extra work to avoid matching the e
in true
.
I haven't explicitly targeted the array values
but it could be adapted accordingly. How exactly you'd do that depends on whether you want to cope with generic JSON or something a little more targeted to your exact format. You might only put quotes around numbers once they get to a certain length, for example. That would be easy to add by tracking the exact index that a number starts at rather than just using an isNumber
flag.
If I was going to use something like this in production I would write a shed load of unit tests to ensure it really does work.
Upvotes: 0
Reputation: 10466
If you really need to do it by regex then you may try this.
const regex = /(-?\d+(\.\d+)?)(?![^,]*")/g;
const str = `{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}`;
const subst = `"$1"`;
const result = str.replace(regex, subst);
console.log(result);
UPDATE AS per the comment:
(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])
const regex = /(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])/g;
const str = `{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,"test 123.3,2",0,"test 123.32",0,0,"","adsa22s22",0]}}`;
const subst = `$1"$2"`;
const result = str.replace(regex, subst);
console.log(result);
Upvotes: 1
Reputation: 68413
Parse them into a JS object first
var obj = JSON.parse( jsonString );
then
obj.data.values = obj.data.values.map( function( item ){ return !isNaN( item ) ? String( item ) : item; });
Convert it back to JSON string format
jsonString = JSON.stringify( obj );
However, if the numerals are beyond what javascript objects can take, then use this regex based solution
var str = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}';
str = str.replace(/[,|\[](\-){0,1}\d+(\.\d+)*(?=[,|\]])/g, function(match){ var firstChar = match.charAt(0); match = match.substring( 1 ); return firstChar + "\"" + match + "\"" ; });
console.log( str );
Upvotes: 0
Reputation: 1050
let obj = JSON.parse(response);
obj.values = obj.values.map(item => typeof item === 'number' ? '"'+item+'"');
console.log(JSON.stringify(obj));
or with es5
obj.values = obj.values.map(function(item) {
return typeof item === 'number' ? '"'+item+'"';
}
or instead of typeof item === 'number' you can use ! isNaN(item)
Upvotes: 0
Reputation: 30739
You simply have a loop to check the value is a number or float value and convert to string.
var obj1 = {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}};
obj1.data.values.forEach(function(value, index, theArray) {
if (!isNaN(value) || value.toString().indexOf('.') != -1)
{
theArray[index] = value.toString();
}
});
console.log(obj1);
Upvotes: 1
Reputation: 166
You can loop through the data and convert it into string as shown below:
var data = {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}
var values = [];
for (var i = 0 ; i < data.data.values.length ; i ++) {
values.push(String(data.data.values[i]));
}
data.data.values = values;
console.log(data);
Upvotes: 1