Milen Grigorov
Milen Grigorov

Reputation: 362

JavaScript regex to match numbers in array

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

Answers (6)

skirtle
skirtle

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

Mustofa Rizwan
Mustofa Rizwan

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);

Regex Demo

UPDATE AS per the comment:

(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])

Demo 2

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

gurvinder372
gurvinder372

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

Arsen Ghazaryan
Arsen Ghazaryan

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

Ankit Agarwal
Ankit Agarwal

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

JosephC
JosephC

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

Related Questions