2017-03-29 3 views
1

Im folgenden Code serialisiere ich ein Objekt mit Json.Net. Dieser Json hat eingebettete Typnamen. Ich ändere dann einen der Typnamen, um einen Fehler zu erzeugen (dies ist ein Test, ich habe es mit einem echten Problem in einem bestehenden Projekt zu tun). Wenn ich den JSON deserialize, erwarte ich, ein Objekt zurück zu erhalten, das einen Nullwert für die Eigenschaft mit dem Namen des fiedled Typen hat. Stattdessen scheißt der Serializer und gibt null zurück. Sind meine Erwartungen richtig? Kann ich die Einstellungen irgendwie ändern, so dass ich ein Nicht-Null-Objekt für mein Root-Objekt bekomme? Beachten Sie, dass der zweite Fehler, den ich erhalte, darauf hindeutet, dass ein Fehler im Serializer vorliegt.Unerwarteter Fehler beim Deserialisieren unbekannter Typen mit 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 { } 
} 

Antwort

1

aktualisieren

Diese issue hat in Json.NET 10.0.2 in this submission fest.

Original-Antwort

Das sieht ein Fehler in Json.NET sein. Wenn ich JsonSerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.ReadAhead setzen dann geht das Problem weg:

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

Es ist jedoch nicht erforderlich sein sollte, diese Einstellung zu aktivieren, die Eigenschaften Lesen der Metadaten ermöglicht einschließlich "$type" die sich irgendwo in einem JSON-Objekt, und nicht nur als erste Eigentum. Wahrscheinlich wird der Fehler zufällig behoben, da das gesamte JSON-Objekt vor dem Beginn der Deserialisierung geladen werden muss.

Sie könnten report an issue, wenn Sie möchten.

ein bisschen Debuggen, das Problem scheint zu sein, dass, weil die innere MyTest Objekt nicht aufgebaut werden kann, wird die Ausnahme von JsonSerializerInternalReader.PopulateObject() abgefangen und behandelt, während A das äußere Objekt bevölkern. Aus diesem Grund wird die JsonReader nicht nach dem inneren verschachtelten Objekt erweitert, so dass der Leser und der Serializer in einem inkonsistenten Zustand bleiben. Dies erklärt die zweite Ausnahme und die eventuelle Ausnahme Additional text found in JSON string after finishing deserializing object. Path ''.

+1

Ich berichtete dies als [Problem] (https://github.com/JamesNK/Newtonsoft.Json/issues/1266#event-1025062578), und es wurde behoben. – AbleArcher

Verwandte Themen