Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
39
rated 0 times [  41] [ 2]  / answers: 1 / hits: 18403  / 12 Years ago, sun, may 13, 2012, 12:00:00

An AJAX call is returning a response text that includes a JSON string. I need to:




  1. extract the JSON string

  2. modify it

  3. then reinsert it to update the original string



I am not too worried about steps 2 and 3, but I can't figure out how to do step 1. I was thinking about using a regular expression, but I don't know how as my JSON might have multiple levels with nested objects or arrays.


More From » regex

 Answers
45

You cannot use a regex to extract JSON from an arbitrary text. Since regexes are usually not powerful enough to validate JSON (unless you can use PCRE) they also cannot match it - if they could, they could also validate JSON.



However, if you know that the top-level element of your JSON is always an object or array, you can go by the following approach:




  • Find the first opening ({ or [) and last closing (} or ]) brace in your string.

  • Try to parse that block of text (including the braces) using JSON.parse(). If it succeeded, finish and return the parsed result.

  • Take the previous closing brace and try parsing that string. If it succeeds, you are done again.

  • Repeat this until you got no brace or one that comes before the current opening brace.

  • Find the first opening brace after the one from step 1. If you did not find any, the string did not contain a JSON object/array and you can stop.

  • Go to step 2.



Here is a function that extracts a JSON object and returns the object and its position. If you really need top-level arrays, too, it should be to extend:



function extractJSON(str) {
var firstOpen, firstClose, candidate;
firstOpen = str.indexOf('{', firstOpen + 1);
do {
firstClose = str.lastIndexOf('}');
console.log('firstOpen: ' + firstOpen, 'firstClose: ' + firstClose);
if(firstClose <= firstOpen) {
return null;
}
do {
candidate = str.substring(firstOpen, firstClose + 1);
console.log('candidate: ' + candidate);
try {
var res = JSON.parse(candidate);
console.log('...found');
return [res, firstOpen, firstClose + 1];
}
catch(e) {
console.log('...failed');
}
firstClose = str.substr(0, firstClose).lastIndexOf('}');
} while(firstClose > firstOpen);
firstOpen = str.indexOf('{', firstOpen + 1);
} while(firstOpen != -1);
}

var obj = {'foo': 'bar', xxx: '} me[ow]'};
var str = 'blah blah { not {json but here is json: ' + JSON.stringify(obj) + ' and here we have stuff that is } really } not ] json }} at all';
var result = extractJSON(str);
console.log('extracted object:', result[0]);
console.log('expected object :', obj);
console.log('did it work ?', JSON.stringify(result[0]) == JSON.stringify(obj) ? 'yes!' : 'no');
console.log('surrounding str :', str.substr(0, result[1]) + '<JSON>' + str.substr(result[2]));


Demo (executed in the nodejs environment, but should work in a browser, too): https://paste.aeum.net/show/81/


[#85611] Friday, May 11, 2012, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
johannatorim

Total Points: 599
Total Questions: 124
Total Answers: 100

Location: Virgin Islands (U.S.)
Member since Fri, May 7, 2021
3 Years ago
;