Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to parse json string contains circular reference in javascript?

I have the following json string in javascript. This string contains a circular references. I want to parse this string in such a way that the reference will be replaced by its actual object. I use Json.Parse but it creates the json object with references. Is there any way by whihc i can achieve this ?

{
  "$id": "1",
  "$values": [
    {
      "$id": "2",
      "Event": {
        "$id": "3",
        "Invitaions": {
          "$id": "4",
          "$values": [
            {
              "$ref": "2"
            },
            {
              "$id": "5",
              "Event": {
                "$ref": "3"
              },
              "Id": 2,
              "Name": "test2",
              "Date": "24",
              "EventId": 1
            }
          ]
        },
        "Id": 1,
        "Name": "marriage",
        "Address": "abcd"
      },
      "Id": 1,
      "Name": "test1",
      "Date": "23",
      "EventId": 1
    },
    {
      "$ref": "5"
    },
    {
      "$id": "6",
      "Event": {
        "$id": "7",
        "Invitaions": {
          "$id": "8",
          "$values": [
            {
              "$ref": "6"
            }
          ]
        },
        "Id": 2,
        "Name": "birthday",
        "Address": "abcd"
      },
      "Id": 3,
      "Name": "test3",
      "Date": "25",
      "EventId": 2
    }
  ]
} 
like image 811
user1740381 Avatar asked Oct 04 '22 21:10

user1740381


2 Answers

This should do it:

function resolveReferences(json) {
    if (typeof json === 'string')
        json = JSON.parse(json);

    var byid = {}, // all objects by id
        refs = []; // references to objects that could not be resolved
    json = (function recurse(obj, prop, parent) {
        if (typeof obj !== 'object' || !obj) // a primitive value
            return obj;
        if ("$ref" in obj) { // a reference
            var ref = obj.$ref;
            if (ref in byid)
                return byid[ref];
            // else we have to make it lazy:
            refs.push([parent, prop, ref]);
            return;
        } else if ("$id" in obj) {
            var id = obj.$id;
            delete obj.$id;
            if ("$values" in obj) // an array
                obj = obj.$values.map(recurse);
            else // a plain object
                for (var prop in obj)
                    obj[prop] = recurse(obj[prop], prop, obj)
            byid[id] = obj;
        }
        return obj;
    })(json); // run it!

    for (var i=0; i<refs.length; i++) { // resolve previously unknown references
        var ref = refs[i];
        ref[0][ref[1]] = byid[refs[2]];
        // Notice that this throws if you put in a reference at top-level
    }
    return json;
}            
like image 60
Bergi Avatar answered Oct 12 '22 02:10

Bergi


You should check out Douglas Crockfords JSON-js repo on github: https://github.com/douglascrockford/JSON-js

There's a cycle.js in there that helps you do exactly what you're looking for.

like image 33
Kvam Avatar answered Oct 12 '22 02:10

Kvam