2016-10-09 3 views
5

私は奇妙な問題に遭遇しました。正しい文字列である{"text":"s","cursorPosition":189,"dataSource":"json_northwind",が与えられても、それは引き続き正しく解析されます。Newtonsoft.Jsonが間違ったjsonをパーズします

これはクラスである:ここでは

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; } 
} 

は驚くほど成功したテストです:

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(); 

は、ライブラリーは、いくつか緩ん解析規則を持っていないか、または多分これはバグでしょうか?私は、ライブラリ、バージョン9.0.1

答えて

5

更新

Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038は、この質問のために開かれた問題です。変更セット0721bd4Json.NET release 10.0.1に修正されました。あなたはJson.NETにバグを発見した

オリジナル回答

。オブジェクトがパラメータ化されたコンストラクタで構築されている場合にのみ発生します。私は非パラメータ化コンストラクタを持っているあなたのオブジェクトを変更する場合:

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; } 
} 

その後Json.NETは正しくJsonSerializationExceptionをスローします。

バグの原因は次のとおりです。パラメータのないコンストラクタを使用してオブジェクトを作成する場合、Json.NETは最初にオブジェクトを構築してからJsonSerializerInternalReader.PopulateObject()を入力します。あなたが見ることができるように

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; 
    } 

、オブジェクトが実際に閉じていることを確認するためのロジックif (!finished)があります:このメソッドは、次の(簡体字)のロジックを持っています。

パラメータ化コンストラクタでオブジェクトを作成するときにオブジェクトが構築される前に、プロパティがJsonSerializerInternalReader.ResolvePropertyAndCreatorValues()を使用して、読んでいる:

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; 
    } 

あなたはexitが真であることには同等のチェックはありません見ることができるように。

問題Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038がこのために開かれました。

+0

@Łukasz - OK、私は先に進んで問題を報告しました[閉じられていないオブジェクトを逆シリアル化するには、オブジェクトにパラメータ化されたコンストラクタがあるときに成功します。 #1038](https://github.com/JamesNK/Newtonsoft.Json/issues/1038)。 – dbc

+1

ああ、私は進行中でしたが、私はそれをやめるでしょう。手伝ってくれてありがとう –

関連する問題