1

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.

6
  • 2
    Use a JSON parser. If I could comment this a dozen times, I would. You might use a regex along the way, but regex should not be the primary solution here I think. Commented Sep 19, 2017 at 6:08
  • 2
    Why make numbers into strings though? If there's one thing I've learned it's let primitive types retain their native type. Commented Sep 19, 2017 at 6:09
  • Most likely you are taking the wrong approach and no need to convert numbers to strings. Since they are numbers... Commented Sep 19, 2017 at 6:11
  • I am converting them because I need to work with big numbers, which JS doesn't support, I only need to get these values and place them on the page. Big number is this: 9223372036854775807. Try to place it to your console like a number. If there is better way to do this I will be happy to use it but I don't know it. So I am converting them to string and then parse them with JSON parser. Commented Sep 19, 2017 at 6:15
  • how do you generate this JSON? why don't you make obj.data.values an String[] before/when building this JSON? Is there really a problem with these numbers being numbers and not strings, when you only want to place them on the page, as you said? So many questions, just to avoid this hack Commented Sep 19, 2017 at 6:25

6 Answers 6

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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

3 Comments

Thanks for the answer but the big numbers will be lost with this method.
Javascript does not support large numbers as they truncate them so to preserve them you need to send those as a string from server itself
Yes, I know that and that's why I ask the question. But I can't change the server, this is server on specific device, and can't be changed like that.
1

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

9 Comments

I don't believe this works for the "test 123.32" example found in the original test data.
Just one more question, if I have ","adsa22s22"," it will match 2 also, how can I escape them matching?
@MilenGrigorov does that answer your problem now ?
I can't speak as to the OP's requirements but something like "test 123.32, 16" would be very difficult to handle correctly using a RegExp.
Oh @skirtle just gave good example, now I am wondering if it possible to catch every single case.
|
0

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.

Comments

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

1 Comment

When I hit the first line "let obj = JSON.parse(response);" I lost the big numbers because JS doesn't support them. Thanks anyway, some guys above give me good regex.
0

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

3 Comments

I am converting them because I need to work with big numbers, which JS doesn't support, I only need to get these values and place them on the page. Big number is this: 9223372036854775807. Try to place it to your console like a number. If there is better way to do this I will be happy to use it but I don't know it. So I am converting them to string and then parse them with JSON parser.
@MilenGrigorov I got it now, parsing to json/number approach won't work.
it works good now, thank you but I already accepted the answer by Rizwan Tuman.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.