6

Might be a duplicate question, but couldn't find the answer. I want to stringify a javascript object that contains some JSON strings as values.

For example:

var obj = {id:1, options:"{\"code\":3,\"type\":\"AES\"}"};

As you see, the value for key 'options' is a JSON string. I want to stringify the object 'obj', without double stringifying the inner JSON string.

Is there any clean and neat solution for this, except parsing each value with JSON string and stringifying the object?

Jeff
  • 524
  • 5
  • 17
  • 1
    The only clean way is to avoid mixing JSON and JavaScript objects in the first place. – str Jun 12 '17 at 09:41
  • 2
    I am pretty curious as to how you ended up with an escaped JSON string in a JSON structure in the first place. Ideally, `obj.options` should be a JSON object and not a string in the present case. If you cannot change that, unfortunately, but you know which properties are JSON and which aren't, you could use `JSON.parse()` on the property, replace the string value and then call `JSON.stringify()`. – KevinLH Jun 12 '17 at 09:43
  • Do you know ahead of time what properties of the object contain stringified JSON? – PeterMader Jun 12 '17 at 09:45
  • 1
    @KevinLH I was retrieving some data from a legacy relational database on node.js that has JSON strings as values in few columns. I know I can parse each JSON strings and then stringify the whole object, but I was curious if there's any other simpler solution for that. – Jeff Jun 12 '17 at 09:52
  • **A value cannot become property.** So even if you replace all `\ ` , the value of option will be just a string value. To make the value present in `options` as a part of main `obj` you have to handle it personally (by parsing it as JSON). – S Jayesh Jun 12 '17 at 10:13

4 Answers4

4

Assuming you don't know which properties are JSON, you could use the replacer function parameter on JSON.stringify to check if a value is a JSON string. The below example tries to parse each string inside a try..catch , so is not the most efficient, but should do the trick (on nested properties as well)

var obj = {id:1, options:"{\"code\":3,\"type\":\"AES\"}"};

function checkVal(key,val){
 if(typeof val === 'string'){
  try{return JSON.parse(val);}catch(e){}
  }
  return val;
}

var res = JSON.stringify(obj,checkVal);

console.log('normal output', JSON.stringify(obj))
console.log('with replacer', res);
Me.Name
  • 12,259
  • 3
  • 31
  • 48
1

No, you can't do that.
If you did not encode that string, JSON.parse will not return a correct string.

The cleanest solution to do that is use JSON for obj.options, and stringify it when you need to use it.

attempt0
  • 639
  • 5
  • 14
  • Why is this the accepted answer? You shouldn't just accept "no you can't do that." – user Oct 11 '22 at 18:03
  • @user instead of using more bad code to patch another problem. My suggestion is that you should fix the original problem first. The top answer is some bad code that patches a problem. And now if the actual JSON object contains the string "{}", it gets stringify incorrectly. I believe the top answer shouldn't encourage a bad practice which might cause surprised result. – attempt0 Oct 13 '22 at 05:03
  • And based on that, what he described is indeed impossible. JSON is supposed to return the exact same thing when stringify and then parsed so storing it without escaping is just a wrong idea imo. – attempt0 Oct 13 '22 at 05:04
0

In this case, you need to parse options to JSONObject first. You can do this using following two approaches:

Approach 1:

var obj = {id:1, options:"{\"code\":3,\"type\":\"AES\"}"};
obj.options  = JSON.parse(obj.options);
console.log(JSON.stringify(obj));

Approach 2:

var obj = {id:1, options:"{\"code\":3,\"type\":\"AES\"}"};

var result = JSON.stringify(obj, function(key, val) {
    if (key === "options"){
            return JSON.parse(val);
        }else{
            return val;
        }
});

console.log(result);

Now this will stringify options only once.

Sachin Gupta
  • 7,805
  • 4
  • 30
  • 45
-1

You could do like this

var obj = {id:1, options:"{\"code\":3,\"type\":\"AES\"}"};

var options  =JSON.parse(obj.options);

obj.options = options;

console.log(obj);
Dinesh undefined
  • 5,490
  • 2
  • 19
  • 40