-4

I have a string like

"Something has happened {\"prop1\":{\"name\":\"foo\"}}"

and I would like to parse out the JSON so that I can format the string. Such as:

Something has happened 
{
   "prop1":{
    "name":"foo"
     }
}

In JavaScript, what would be a good way to accomplish this.

There can be multiple object in the string and also the object will not be known it could contain many nested objects or arrays. Thanks in advance.

Tim Scriv
  • 670
  • 7
  • 17
  • dupe? http://stackoverflow.com/questions/4935632/parse-json-in-javascript – httpNick Sep 13 '16 at 23:18
  • *"I would like to parse out the JSON so that I can format the string."* What exactly does that mean? I'm not sure I understand the issue. The string literal `"Something has happened {\"prop1\":{\"name\":\"foo\"}}"` produces exactly the character sequence you seem to want as result? – Felix Kling Sep 13 '16 at 23:23
  • *"so that I can format the string"* - Do you just want to pretty print the *whole* string in the format shown, or do you need to specifically extract the bits of JSON? Will you assume that any use of `{` indicates the start of JSON within the larger string? You mentioned nested arrays, but can the outer object be an array like `"Something something [1,2,3]"`? – nnnnnn Sep 14 '16 at 00:49
  • @nnnnnn The minimum would be simply pretty-printing the string but extracting the Json object is fine too. Yes it is possible yo have an array as the outer object. – Tim Scriv Sep 14 '16 at 01:18
  • @FelixKling I updated my question so that the format is better represented. I need to be able to pretty print this object. – Tim Scriv Sep 14 '16 at 01:20
  • @httpNick no. I do not need to take a stringified object and parse it. I have a string that can contain Json objects or arrays and I need to parse out the parts that are Json so I can pretty print it. – Tim Scriv Sep 14 '16 at 01:21

2 Answers2

1

The minimum would be simply pretty-printing the string

OK then. Well a really simple, non-optimised, not-necessarily robust pretty print function might look something like this:

function basicPrettyPrint(str) {
  var output = '';
  var indentLevel = 0;
  var indent = '  ';
  var inQuotes = false;
  for (var i = 0; i < str.length; i++) {
    var current = str[i];
    if (current === '"' && indentLevel > 0) {
      inQuotes = !inQuotes;
      output += current;
    } else if (inQuotes) {
      output += current;
    } else if (current === ',' && indentLevel > 0) {
      output += ',\n' + indent.repeat(indentLevel);
    } else if (current === '{' || current === '[') {
      if (indentLevel === 0) output += '\n';
      output += current + '\n' + indent.repeat(++indentLevel);
    } else if (current === '}' || current === ']') {
      output += '\n' + indent.repeat(--indentLevel) + current;
      if (indentLevel === 0) output += '\n';
    } else {
      output += current;
    }
    if (indentLevel < 0) {
      // parse failure: unbalanced brackets. Do something.
    }
  }
  return output;
}

var input = 'Here is a "simple" object, for testing: {"prop1":{"name":"foo"}}And here is a more complicated one that has curly brackets within one of the property values:{"prop1":"{this is data, not an object}","arr":[1,{"a":"1","b":{"x":1,"y":[3,2,1]}},3,4]}And a non-nested array:[1,2,3]';

console.log(basicPrettyPrint(input));

The above doesn't allow for escaped quotation marks within properties, and probably a bunch of other things I didn't think of for purposes of a quick demo, but I leave those things as exercises for the reader...

P.S. The string .repeat() method might need to be polyfilled.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • Yeah I thought about doing this type of procedural approach but figured someone might have a clever solution. Thank you – Tim Scriv Sep 14 '16 at 02:19
0

Can we assume that the '{' and '}' indicate the start and end of the json. If so, you can get a substring; see code below. You could do the same thing with regular expressions.

    var str = "Something has happened {\"prop1\":{\"name\":\"foo\"}}"
    var start = str.indexOf("{");
    var end = str.lastIndexOf("}");
    var json = str.substr(start, end);
Darin Cardin
  • 627
  • 1
  • 4
  • 10
  • The string doesn't only contain an object it can contain some words that are not in the object, plus there can be multiple objects in one string like "from {} to {}" – Tim Scriv Sep 13 '16 at 23:24
  • If I can have multiple object then this would break like in my reply above "from {} to {}" – Tim Scriv Sep 14 '16 at 01:22