8

Web APIに次のメソッドがあります

public void Put(string id, [FromBody]IContent value) {
    //Do stuff
}

バックボーンjsを使用して、フィドラーを使用して次のJSONをサーバーに送信しています。値はnullです。

{
    "id": "articles/1",
    "heading": "Bar",
    "$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"
}

しかし、JSON オブジェクトに最初に $type プロパティを追加すると、逆シリアル化は正常に機能します。以下を参照してください。

{
 "$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
  "id": "articles/1",
  "heading": "Bar" 
}

最初のプロパティではなく、オブジェクト内の任意の場所にある $type プロパティをチェックするように newtonsoft を構成することは可能ですか? または、常に$typeJSON オブジェクトの最初にプロパティを追加するようにバックボーンを構成できますか?

4

4 に答える 4

4

まず、私の知る限り、Json.NET のコードは、型を読み取るためだけにオブジェクト全体をメモリに保持しないように最適化されています。したがって$type、最初のプロパティとして配置することをお勧めします。

次に、JsonConverter最初にJObject(Loadメソッドを使用して) を読み取り、手動で$typeプロパティを読み取り、シリアライザーの から型を取得SerializationBinderし、値を作成して から値を設定する独自のものを作成できますJObject

第三に、セキュリティについてです。Json.NET$typeは良いアイデアのように聞こえるかもしれませんが、多くの場合そうではありません。Json.NET は、JSON ファイルに型を書き込むだけで、任意のアセンブリから任意のオブジェクト型を作成できます。指定した型のみを許可する辞書でcustom を使用することをお勧めします。私のプライベート フレームワークで例を見つけることができます ( fromの値の取得もサポートしています)。SerializationBinder$typeJsonObjectAttribute

https://github.com/Athari/Alba.Framework/blob/742ff1aeeb114179a16ca42667781944b26f3815/Alba.Framework/Serialization/DictionarySerializationBinder.cs

(このバージョンでは、他のクラスのいくつかのメソッドを使用していますが、それらは些細なことです。後のコミットにより、クラスはより複雑になりました。)

于 2013-04-04T12:16:10.647 に答える
4

シリアライザー (JSON.NET を含む) を構成して、受信ペイロードからオブジェクト型を読み取ることは強くお勧めしません。これは歴史的に、Web アプリケーションの多数の脆弱性の原因となっています。代わりに、パブリック エントリ ポイントをアクションに変更して、実際の型をバインドされたパラメーターとして受け取り、必要に応じて内部のテスト可能なメソッドに委任します。

于 2013-03-22T16:17:42.603 に答える
3

どうやら同じ質問があり、誰かが答えを見つけました。答えを共有して彼にすべてのクレジットを与える適切な方法がわからないが、これはリンクです: Newtonsoft JSON.net deserialization error where fields in JSON change order

そしてこれは男です: https://stackoverflow.com/users/3744182/dbc

于 2015-04-09T22:51:05.350 に答える
1

これはバックボーンで機能しますが、すべてのブラウザーが同じように動作するかどうかはわかりません。基本的に、すべてのブラウザがアイテムを追加された順序で保持するという保証はありません。


MyModel = Backbone.Model.extend({

  // ...

  toJSON: function(){
    // build the "$type" as the first parameter
    var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
    // get the rest of the data
    _.extend(json, Backbone.Model.prototype.toJSON.call(this));
    // send it back, and hope it's in the right order
    return json;
  }


});

ただし、特定の位置でそれを必要とせずに、NewtonSoft の JSON デシリアライザーを動作させる方がよいでしょう。うまくいけば、それが可能になるでしょう。

于 2013-03-22T13:13:32.590 に答える