Pawel
Pawel

Reputation: 21

parse JSON manually

I need to parse a JSON string such as that shown below:

var json = 
"{\
foo: {\
  bar: 'something',\
  baz: {\
    jack: 'other',\
    jill: 5\
  },\
  bob: {\
    bill: 'hello',\
    bilbo: 11,\
      baggins: {\
        fizz: 'buzz'\
      }\
    }\
  }\
}";

I can't use eval or a JS library to parse this into a JavaScript object. All I have available to me are the methods of String, Object, etc.

The result of the parsing should be a JS object whose properties correspond to those of the JSON. The values of the JSON properties will only ever be numbers string or other objects, i.e. no arrays.

I'm really struggling with this, so if anyone could help me get started (or already has a completely solution), it would be much appreciated.

Upvotes: 0

Views: 7599

Answers (4)

Code Disease
Code Disease

Reputation: 1

There may be reasons to use a custom JSON parsing method but in case this was what you were looking for...

JavaScript has this all built in for you.

Here's an example:

var json = JSON.parse('{"myKey":"myValue"}');

console.log(json); // {myKey:'myValue'}

Upvotes: 0

pimvdb
pimvdb

Reputation: 154818

Building upon phihag's answer, I just made this up. It might be a start for you.

It does not support:

  • Spaces outside key/value
  • Any of ,{}:" as key/value
  • Arrays
  • No error handling
  • (Probably more - I haven't tested this extensively)

The code:

var json = '{"a":{"b":"test"},"c":123,"d":{"nested":{"key":null}}}';

var split = function(str, delimiter, func) {
    var res = [];
    var before = 0;
    for(var i = 0; i < str.length; i++) {
        if(str[i] === delimiter) {
            if(func(str, i) === true) {
                res.push(str.substring(before, i));
                before = i + 1;
            }
        }
    }
    res.push(str.substring(before));
    return res;
};

var amountbefore = function(str, pos, character) {
    var amount = 0;
    for(var i = 0; i < pos; i++) {
        if(str[i] === character) {
            amount++;
        }
    }
    return amount;
};

var parse = function(obj) {
    var stripped = obj.slice(1, -1);
    var splitted = split(stripped, ",", function(str, i) {
        return amountbefore(str, i, "{") === amountbefore(str, i, "}");
    });
    var res = {};
    if(stripped === "") return res;
    for(var i = 0; i < splitted.length; i++) {
        var spl = split(splitted[i], ":", function(str, i) {
            return amountbefore(str, i, "{") === amountbefore(str, i, "}")
        });
        var val;
        if(spl[1][0] === "n")     val = null;
        if(/^\d/.test(spl[1][0])) val = spl[1] - 0;
        if(spl[1][0] === "\"")    val = spl[1].slice(1, -1);
        if(spl[1][0] === "{")     val = parse(spl[1]);
        res[spl[0].slice(1, -1)] = val;
    }
    return res;
};

parse(json); // parses the JSON string

Upvotes: 3

phihag
phihag

Reputation: 287775

Luckily, JSON is very easy to parse: Just write parsing functions for each construct. For example, here's one that parses null:

function parseNull(input, position) {
    if (input.substr(position, 4) != "null") throw "Cannot parse as null";
    return {result:null, position: position+4};
}

Implement a similar function for each construct, i.e. parseString, parseArray, parseObject, ... .

Given these functions, write a function parse that skips white-space and decides which of the above functions to call based on the first non white-space character. If that's n, call parseNull, if {, call parseObject etc. . Note that parseArray and parseObject will call parse themselves.

Upvotes: 2

anton_byrna
anton_byrna

Reputation: 2555

var json = Function("return {\
foo: {\
  bar: 'something',\
  baz: {\
    jack: 'other',\
    jill: 5\
  },\
  bob: {\
    bill: 'hello',\
    bilbo: 11,\
      baggins: {\
        fizz: 'buzz'\
      }\
    }\
  }\
}")(); // object

Upvotes: 4

Related Questions