How to restore original object/type from JSON?

前端 未结 6 1668
旧时难觅i
旧时难觅i 2020-12-05 19:38

Its easy to load JSON into an object in javascript using eval or JSON.parse.

But if you have a proper \"class\" like function, how do you get the JSON data into it?<

相关标签:
6条回答
  • 2020-12-05 19:55

    Easiest way is to use JSON.parse to parse your string then pass the object to the function. JSON.parse is part of the json2 library online.

    0 讨论(0)
  • 2020-12-05 19:56

    I;m not too much into this, but aPerson.addAddress should not work, why not assigning into object directly ?

    aPerson.address.push(someAddress);
    alert(aPerson.address); // alert [object object]
    
    0 讨论(0)
  • 2020-12-05 20:00

    Just in case someone needs it, here is a pure javascript extend function (this would obviously belong into an object definition).

      this.extend = function (jsonString){
        var obj = JSON.parse(jsonString)
        for (var key in obj) {
            this[key] = obj[key]
            console.log("Set ", key ," to ", obj[key])
            }   
        } 
    

    Please don't forget to remove the console.log :P

    0 讨论(0)
  • 2020-12-05 20:02

    A little late to the party, but this might help someone. This is how I've solved it, ES6 syntax:

    class Page 
    {
       constructor() {
          this.__className = "Page";
       }
    
       __initialize() {
           // Do whatever initialization you need here.
           // We'll use this as a makeshift constructor.
           // This method is NOT required, though
       }
    }
    
    class PageSection
    {
       constructor() {
          this.__className = "PageSection";
       }
    }
    
    class ObjectRebuilder
    {
        // We need this so we can instantiate objects from class name strings
        static classList() {
            return {
                Page: Page,
                PageSection: PageSection
            }
        }
    
        // Checks if passed variable is object.
        // Returns true for arrays as well, as intended
        static isObject(varOrObj) {
            return varOrObj !== null && typeof varOrObj === 'object';
        }
    
        static restoreObject(obj) {
            let newObj = obj;
    
            // At this point we have regular javascript object
            // which we got from JSON.parse. First, check if it
            // has "__className" property which we defined in the
            // constructor of each class
            if (obj.hasOwnProperty("__className")) {
                let list = ObjectRebuilder.classList();
    
                // Instantiate object of the correct class
                newObj = new (list[obj["__className"]]);
    
                // Copy all of current object's properties
                // to the newly instantiated object
                newObj = Object.assign(newObj, obj);
    
                // Run the makeshift constructor, if the
                // new object has one
                if (newObj.__initialize === 'function') {
                    newObj.__initialize();
                }
            }
    
            // Iterate over all of the properties of the new
            // object, and if some of them are objects (or arrays!) 
            // constructed by JSON.parse, run them through ObjectRebuilder
            for (let prop of Object.keys(newObj)) {
                if (ObjectRebuilder.isObject(newObj[prop])) {
                    newObj[prop] = ObjectRebuilder.restoreObject(newObj[prop]);
                }
            }
    
            return newObj;
        }
    }
    
    let page = new Page();
    let section1 = new PageSection();
    let section2 = new PageSection();
    
    page.pageSections = [section1, section2];
    
    let jsonString = JSON.stringify(page);
    let restoredPageWithPageSections = ObjectRebuilder.restoreObject(JSON.parse(jsonString));
    
    console.log(restoredPageWithPageSections);
    

    Your page should be restored as an object of class Page, with array containing 2 objects of class PageSection. Recursion works all the way to the last object regardless of depth.

    @Sean Kinsey's answer helped me get to my solution.

    0 讨论(0)
  • 2020-12-05 20:09

    Many frameworks provide an 'extend' function that will copy fields over from one object to another. You can combine this with JSON.parse to do what you want.

    newPerson = new Person();
    _.extend(newPerson, JSON.parse(aPersonJSON));
    

    If you don't want to include something like underscore you can always copy over just the extend function or write your own.

    Coffeescript example because I was bored:

    JSONExtend = (obj, json) ->
      obj[field] = value for own field, value of JSON.parse json
      return obj
    
    class Person
      toString: -> "Hi I'm #{@name} and I'm #{@age} years old."
    
    
    dude = JSONExtend new Person, '{"name":"bob", "age":27}'
    console.log dude.toString()
    
    0 讨论(0)
  • 2020-12-05 20:10

    You need to use a reviver function:

    // Registry of types
    var Types = {};
    
    function MyClass(foo, bar) {
      this._foo = foo;
      this._bar = bar;
    }
    Types.MyClass = MyClass;
    
    MyClass.prototype.getFoo = function() {
      return this._foo;
    }
    
    // Method which will provide a JSON.stringifiable object
    MyClass.prototype.toJSON = function() {
      return {
        __type: 'MyClass',
        foo: this._foo,
        bar: this._bar
      };
    };
    
    // Method that can deserialize JSON into an instance
    MyClass.revive = function(data) {
      // TODO: do basic validation
      return new MyClass(data.foo, data.bar);
    };
    
    var instance = new MyClass('blah', 'blah');
    
    // JSON obtained by stringifying an instance
    var json = JSON.stringify(instance); // "{"__type":"MyClass","foo":"blah","bar":"blah"}";
    
    var obj = JSON.parse(json, function(key, value) {
      return key === '' && value.hasOwnProperty('__type')
        ? Types[value.__type].revive(value)
        : this[key];
    });
    
    obj.getFoo(); // blah
    

    No other way really...

    0 讨论(0)
提交回复
热议问题