2012-12-25 9 views
9

evalまたはJSON.parseを使用してJSONをjavascriptのオブジェクトにロードするのは簡単です。元のオブジェクト/タイプをJSONから復元するには?

しかし、適切な "クラス"のような機能を持っている場合、JSONデータをどのように取得しますか?

など。

function Person(name) { 
    this.name=name; 
    this.address = new Array(); 
    this.friendList; 

    this.promote = function(){ 
    // do some complex stuff 
    } 
    this.addAddress = function(address) { 
    this.address.push(address) 
    } 
} 

var aPersonJSON = '{\"name\":\"Bob\",\"address\":[{\"street\":\"good st\",\"postcode\":\"ADSF\"}]}' 

var aPerson = eval("(" + aPersonJSON + ")"); // or JSON.parse 
//alert (aPerson.name); // Bob 
var someAddress = {street:"bad st",postcode:"HELL"}; 
//alert (someAddress.street); // bad st 
aPerson.addAddress(someAddress); // fail! 

JSONから適切なPersonインスタンスを作成できるようにする必要がありますが、私が得ることのできるのはダムオブジェクトだけです。私はプロトタイプで何かできるかどうか疑問に思っていますか?

JSONの各行を解析し、各変数を対応する関数属性に割り当てる必要がありません。これは難しすぎます。実際のJSONと私が持っている関数は、上記の例よりはるかに複雑です。

関数メソッドをJSON文字列にJSON化できると仮定していますが、結果として得られるデータを可能な限り小さく保つ必要があるため、これはオプションではありません - 私はjavascriptではなくデータを格納しロードしたいメソッドのコード

JSONによって読み込まれたデータをサブオブジェクトとして入れたいと思っています。私が助けることができれば(しかし唯一の方法かもしれません)。

function Person(name) { 
    this.data = {}; 
    this.data.name=name; 
} 

var newPerson = new Person(""); 
newPerson.data = eval("(" + aPersonJSON + ")"); 
alert (newPerson.data.name); // Bob 

+2

JSONを解析するには 'eval'ではなく[' JSON.parse'](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)を使用してください。ターゲットブラウザが 'JSON.parse'をサポートしていない場合(IE7以前)は、Crockfordの' json.js'( 'eval'を内部的に使用しますが、健全性の検証も行います)または' json2。 jsは容易に利用可能である。 –

+0

こんにちは、問題は両方の型のないオブジェクトを生成するevalまたは解析ではない、私は人fuctionにJSONを取得する方法を見つけようとしています。これに関するアイデア? –

+0

@JohnLittleは決してevalを使用しません!多くのセキュリティ問題(コードの挿入など)のソースです[こちらを読む](http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil ) – thepoosh

答えて

2

最も簡単な方法は、JSON.parseを使用して文字列を解析し、そのオブジェクトを関数に渡すことです。 JSON.parseは、オンラインのjson2ライブラリの一部です。

+1

最新のブラウザではJSONメソッドが利用できます...古いブラウザではライブラリをフォールバックとして使用します – charlietfl

+0

'JSON.stringify()'関数は**解析中*ではありません。オブジェクト*をJSON文字列に変換するためのものです。 – Pointy

+0

こんにちは、これは、彼はfuctionの結果の複雑なオブジェクトintotを有効にする方法の要点ですか?私はオブジェクトをトラバースするために非常に複雑なものを書いていない限り、個々のサブオブジェクトとデータ項目をPerson objejectにコピーしなければなりません。 –

8

多くのフレームワークは、あるオブジェクトから別のオブジェクトにフィールドをコピーする '拡張'機能を提供します。これをJSON.parseと組み合わせて、あなたが望むことをすることができます。

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

あなたは常にだけ拡張機能をコピーしたり、独自に作成することができ、アンダースコアのようなものを含めない場合。

CoffeeScriptの例私は退屈していたので:

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

雑多な怒りを負う危険がありますが、Coffeescriptは+1です! –

0

私は、 がなぜ直接オブジェクトに割り当てていない、このにすぎないM、しかしaPerson.addAddressは動作しないでしょうか?あなたはreviver機能を使用する必要が

aPerson.address.push(someAddress); 
alert(aPerson.address); // alert [object object] 
16

// 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 

んが、他の方法が本当に...誰かがそれを必要とする

+1

この関数 'reviver'を呼び出すための規約はありますか? – Bergi

+1

JSONオブジェクトの仕様では、メソッド(および仮引数)を復唱者と呼びます。 –

1

念のため、ここでは純粋なJavaScriptをされていないが、関数 (これを拡張します明らかにオブジェクト定義に属します)。

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]) 
     } 
    } 

console.logを削除することを忘れないでください:少し遅れて相手にP

1

が、これは、誰かを助けるかもしれません。 これは、私はそれを解決しましたかES6の構文は次のとおりです。

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); 

あなたのページには、配列は、クラスPageSectionの2つのオブジェクトを含むと、クラスPageのオブジェクトとして復元する必要があります。再帰は、深さに関係なく最後のオブジェクトまでずっと働きます。

@Sean Kinseyの回答は私の解決に役立ちました。

関連する問題