16

私は最近、Node.js とブラウザー内で JSON を解析して Javascript を渡す作業をかなり行っていて、この難問にぶつかりました。

コンストラクターを使用して作成したオブジェクトは、コンストラクター内のすべての値を個別に初期化しない限り、JSON.stringify を介して完全にシリアル化することはできません! これは、これらのクラスの設計において、私のプロトタイプが本質的に役に立たなくなることを意味します。

以下が期待どおりにシリアル化されない理由を誰かが明らかにすることはできますか?

var ClassA = function () { this.initialisedValue = "You can see me!" };
ClassA.prototype = { initialisedValue : "You can't see me!", uninitialisedValue : "You can't see me!" };
var a = new ClassA();
var a_string = JSON.stringify(a);

何が起こるのですか:

a_string == { "initializedValue" : "私が見えます!" }

私は期待します:

a_string == { "initializedValue" : "私が見える!", "uninitializedValue" : "私が見えない!" }


更新 (01-10-2019):

最後に、@ ncardeli の回答に気付きました。これにより、上記の要件を達成するために次のようなことが可能になります (2019 年に!):

交換 var a_string = JSON.stringify(a);

var a_string = JSON.stringify(a, Object.keys(ClassA.prototype));

完全なコード:

var ClassA = function () { this.initialisedValue = "You can see me!" };
ClassA.prototype = { initialisedValue : "You can't see me!", uninitialisedValue : "You can't see me!" };
var a = new ClassA();
var a_string = JSON.stringify(a, Object.keys(ClassA.prototype));

console.log(a_string)
4

3 に答える 3

16

これがJSONの仕組みだからです。ES5仕様から:

Kを、[[Enumerable]]属性がtrueである値のすべての独自のプロパティの名前で構成される文字列の内部リストとします。

継承されたプロパティが含まれている場合、JSON文字列を解析してJavaScriptオブジェクトに戻すために必要な情報を保持するためのメカニズムが、JSON仕様にないため、これは理にかなっています。あなたの例では、これはどのように解析されますか?

{"initialisedValue": "あなたは私を見ることができます!"、 "uninitialisedValue": "あなたは私を見ることができません!" }

2つのキーと値のペアを持つフラットオブジェクト以外に解析するための情報はありません。

そして、あなたがそれについて考えるならば、JSONはJavaScriptオブジェクトに直接マップすることを意図していません。他の言語は、JSON文字列を名前と値のペアの単純な構造に解析できる必要があります。JSON文字列に完全なJavaScriptスコープチェーンをシリアル化するために必要なすべての情報が含まれている場合、他の言語ではそれを有用なものに解析できない可能性があります。json.orgのダグラスクロックフォードの言葉で:

これらの[ハッシュテーブルと配列]はユニバーサルデータ構造です。事実上すべての最新のプログラミング言語は、何らかの形でそれらをサポートしています。プログラミング言語と互換性のあるデータ形式もこれらの構造に基づいていることは理にかなっています。

于 2012-09-11T12:24:33.057 に答える