2016-10-09 4 views
5

Ich stieß auf ein seltsames Problem: gegeben wie Zeichenfolge {"text":"s","cursorPosition":189,"dataSource":"json_northwind",, die kein richtiges JSON ist, wird es immer noch erfolgreich geparst.Newtonsoft.Json analysiert falsche JSON

ist dies die Klasse:

public class CompletionDataRequest 
{ 
    public CompletionDataRequest(string text, int cursorPosition, string dataSource, string project) 
    { 
     Text = text; 
     CursorPosition = cursorPosition; 
     DataSource = dataSource; 
     Project = project; 
    } 

    public string Text { get; } 
    public int CursorPosition { get; } 
    public string DataSource { get; } 
    public string Project { get; } 
} 

Hier Test, der überraschend erfolgreich:

var s = @"{""text"":""s"",""cursorPosition"":189,""dataSource"":""json_northwind"","; 
var request = JsonConvert.DeserializeObject<CompletionDataRequest>(s); 
request.Text.Should().Be("s"); 
request.CursorPosition.Should().Be(189); 
request.DataSource.Should().Be("json_northwind"); 
request.Project.Should().BeNull(); 

hat die Bibliothek haben einige gelockert Parsen Regeln oder vielleicht ist das ein Fehler? Ich bin Bibliothek Version 9.0.1

Antwort

5

aktualisieren

Ein Problem Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038 wurde für diese Frage eröffnet. Es wurde in Json.NET release 10.0.1 im Änderungssatz 0721bd4 behoben.

Original-Antwort

Sie haben einen Fehler in Json.NET gefunden. Es tritt nur auf, wenn Ihr Objekt mit einem parametrisierten Konstruktor erstellt wird. Wenn ich das Objekt ändern, um einen nicht-parametrisierte Konstruktor habe:

public class CompletionDataRequest 
{ 
    public CompletionDataRequest(string text, int cursorPosition, string dataSource, string project) 
    { 
     Text = text; 
     CursorPosition = cursorPosition; 
     DataSource = dataSource; 
     Project = project; 
    } 

    [JsonConstructor] 
    private CompletionDataRequest() 
    { 
    } 

    [JsonProperty] 
    public string Text { get; private set; } 
    [JsonProperty] 
    public int CursorPosition { get; private set; } 
    [JsonProperty] 
    public string DataSource { get; private set; } 
    [JsonProperty] 
    public string Project { get; private set; } 
} 

Dann wird Json.NET richtig ein JsonSerializationException werfen.

Die Ursache des Fehlers ist wie folgt. Beim Erstellen eines Objekts mit einem parameterlosen Konstruktor erstellt Json.NET zuerst das Objekt und füllt es dann mit JsonSerializerInternalReader.PopulateObject(). Diese Methode hat die folgende (vereinfachte) Logik:

private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id) 
    { 
     bool finished = false; 
     do 
     { 
      switch (reader.TokenType) 
      { 
       case JsonToken.PropertyName: 
       { 
        // Read and process the property. 
       } 
       case JsonToken.EndObject: 
        finished = true; 
        break; 
       case JsonToken.Comment: 
        // ignore 
        break; 
       default: 
        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); 
      } 
     } while (!finished && reader.Read()); 

     if (!finished) 
     { 
      ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object."); 
     } 

     return newObject; 
    } 

Wie Sie sehen können, gibt es Logik if (!finished) zu überprüfen, ob das Objekt tatsächlich geschlossen ist.

Wenn jedoch ein Objekt mit einem parametrisierte Konstruktor erstellen, werden die Eigenschaften zu lesen, bevor das Objekt aufgebaut ist, JsonSerializerInternalReader.ResolvePropertyAndCreatorValues() mit:

private List<CreatorPropertyContext> ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType) 
    { 
     List<CreatorPropertyContext> propertyValues = new List<CreatorPropertyContext>(); 
     bool exit = false; 
     do 
     { 
      switch (reader.TokenType) 
      { 
       case JsonToken.PropertyName: 
        // Read and process the property. 
        break; 
       case JsonToken.Comment: 
        break; 
       case JsonToken.EndObject: 
        exit = true; 
        break; 
       default: 
        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); 
      } 
     } while (!exit && reader.Read()); 

     return propertyValues; 
    } 

Wie Sie gibt es keine gleichwertige Prüfung für exit sehen kann wahr sein.

Ein Problem Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038 wurde dafür geöffnet.

+0

@ Łukasz - OK, ich ging voran und berichtete das Problem, [Deserializing nicht abgeschlossenes Objekt ist erfolgreich, wenn das Objekt einen parametrisierten Konstruktor hat. # 1038] (https://github.com/JamesNK/Newtonsoft.Json/issues/1038). – dbc

+1

Oh, ich war in Arbeit, aber ich werde dann aufhören. Danke für die Hilfe –

Verwandte Themen