2017-03-29 2 views
1

次のコードでは、Json.Netを使用してオブジェクトをシリアル化します。このJsonには型名が埋め込まれています。私はエラーを誘発するためにタイプ名の1つを変更します(これはテストです、私は既存のプロジェクトで実際の問題を扱っています)。私がJsonを逆シリアル化するとき、私は、型名が詰まったプロパティのnull値を持つオブジェクトを取得することを期待しています。代わりに、シリアライザはクラップアウトし、nullを返します。私の期待は正しいですか?どういうわけか設定を変更して、ルートオブジェクトに対してnull以外のオブジェクトを取得できますか?私が得た2番目のエラーは、シリアライザにバグがあることを示唆しています。Json.Netで未知の型を逆シリアル化すると予期しないエラーが発生する

static public class JsonTest 
{ 
    static public void Test() 
    { 
     // Create test object 
     A a = new A 
     { 
      MyTest = new MyTest(), 
     }; 

     // Serialize it. 
     string json = JsonConvert.SerializeObject(a, new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.Auto 
     }); 

     // Fiddle class name to induce error 
     json = json.Replace("+MyTest", "+MyTest2"); 

     // Before: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest, <Assembly>"}} 
     // After: {"MyTest":{"$type":"<Namespace>.JsonTest+MyTest2, <Assembly>"}} 

     // Deserialize 
     A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.Auto, 
      Error = (object sender, ErrorEventArgs e) => 
      { 
       e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type 
      } 
     }); 

     // A second error occurs: Error = {Newtonsoft.Json.JsonSerializationException: Additional text found in JSON string after finishing deserializing object.... 
     // a2 is null 
    } 

    public class A 
    { 
     public ITest MyTest { get; set; } 
    } 

    public interface ITest { } 
    public class MyTest : ITest { } 
} 

答えて

1

更新

このissuethis submissionにJson.NET 10.0.2で修正されています。

オリジナル回答

これはJson.NETのバグに見えます。私はJsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAheadを設定した場合、問題が消える:

// Deserialize 
A a2 = JsonConvert.DeserializeObject<A>(json, new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.Auto, 
    MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead, 
    Error = (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs e) => 
    { 
     Debug.WriteLine(e.ErrorContext.Path); 
     e.ErrorContext.Handled = true; // Should have only one error: the unrecognized Type 
    } 
}); 

Debug.Assert(a2 != null); // No assert. 

しかし、むしろちょうど最初としてよりも、どこにでもJSONオブジェクト内の位置"$type"を含むメタデータプロパティを読み込む可能にする、この設定をオンにする必要はありませんプロパティ。ほとんどの場合、デシリアライズを開始する前にJSONオブジェクト全体をプリロードする必要があるため、バグを偶然に修正する可能性があります。

可能であればreport an issueとすることができます。ビットデバッグ

、問題は、内側MyTestオブジェクトを構築することができないので、外側のオブジェクトAを移入しながら、例外がJsonSerializerInternalReader.PopulateObject()によって捕捉および処理されることであると思われます。このため、JsonReaderは内側のネストされたオブジェクトを越えて進まず、リーダーとシリアライザは矛盾した状態になります。これは第2の例外と、最終的にAdditional text found in JSON string after finishing deserializing object. Path ''例外を説明する。

+1

[問題](https://github.com/JamesNK/Newtonsoft.Json/issues/1266#event-1025062578)として報告しましたが、修正されました。 – AbleArcher

関連する問題