简体   繁体   中英

Split string into JSON and non-JSON part

I have a string like this:

var s = '{ "foo": { "bar": { "baz": 5 } } } Some more content';

Is there a reliable way in JavaScript to split the string into the JSON and non-JSON part? The string always begins with valid JSON, but other than that the JSON can contain anything, so tricks like counting braces won't work.

The best option I see at the moment is to use the json-lint module to get the position of the error and split at the error position.

Any other ideas?

As stated in the comments, you really should look at cleaning up the string that you are working with so that it is only actual JSON.

Nevertheless, if you really want to move forward with the way you have things, here is a way you can do it with just vanilla JavaScript. This assumes as you say, the string always begins with "valid" JSON.

function splitMyJsonString(string) {

    var jsonData = getValidJson(string);

    return [
        jsonData.json,
        string.split('').slice(jsonData.errorIndex).join('')
    ];

    function getValidJson(s) {
        var newString = '';
        for (var i = 0; i < s.length; i++) {
            try {
                return {json: JSON.parse(newString), errorIndex: i}
            }
            catch (e) {
                newString += s.charAt(i);
            }
        }
        return {json: null, errorIndex: 0}
    }
}

What you get back from the function call is an array where at the first index is your parsed JSON as an object, and at the second index is the remaining string (since you asked for a split). If no valid json was found at the beginning of the string, you will get an array back where at the first index is null .

var s = '{ "foo": { "bar": { "baz": 5 } } } Some more content';
console.log(splitMyJsonString(s)); // logs: [Object, " Some more content"]

// If no valid JSON is at the start of the string...
var z = 'Some more content';
console.log(splitMyJsonString(z)); // logs [null, "Some more content"]

First, we split the entire string into an array for array slicing later. Then we get the valid JSON from the beginning of the string. The way we do this is be trying to parse a piece at a time until we get an actual pass (sigh). Once that passes, or doesn't we return the values. I left a few gaps in the explanation, but the main points have been covered.

 function splitMyJsonString(string) { var jsonData = getValidJson(string); return [ jsonData.json, string.split('').slice(jsonData.errorIndex).join('') ]; function getValidJson(s) { var newString = ''; for (var i = 0; i < s.length; i++) { try { return { json: JSON.parse(newString), errorIndex: i } } catch (e) { newString += s.charAt(i); } } return { json: null, errorIndex: 0 } } } var s = '{ "foo": { "bar": { "baz": 5 } } } Some more content'; console.log(splitMyJsonString(s)); // logs: [Object, " Some more content"] // If no valid JSON is at the start of the string... var z = 'Some more content'; console.log(splitMyJsonString(z)); // logs [null, "Some more content"] 

Using the same approach as KevBot but potential elimination a lot of try {} catch(e) {} :

var s = '{ "foo": { "bar": { "baz": 5 } } } Some mo}re }content';
var offset = s.length + 1;
while (offset > 0) {
    offset = s.lastIndexOf('}', offset - 1);
    var maybe_json = s.slice(0, offset + 1);
    try {
        var json = JSON.parse(maybe_json);
    break;
    } catch (e) {}
}
var rest = s.slice(offset + 1);

console.log(json); // { "foo": { "bar": { "baz": 5 } } }
console.log(rest); // " Some mo}re }content"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM