2016-10-09 31 views
5

Tôi gặp phải một vấn đề lạ: với chuỗi {"text":"s","cursorPosition":189,"dataSource":"json_northwind", không phải là một json đúng, nó vẫn được phân tích thành công.Newtonsoft.Json phân tích cú pháp json không chính xác

này là lớp:

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

Dưới đây là bài kiểm tra đó đáng ngạc nhiên thành công:

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

hiện các thư viện có một số nới lỏng quy tắc phân tích hoặc có thể đây là lỗi? Tôi thư viện phiên bản 9.0.1

Trả lời

5

Cập nhật

Một vấn đề Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038 được mở cho câu hỏi này. Nó đã được sửa trong Json.NET release 10.0.1 trong bộ thay đổi 0721bd4.

gốc trả lời

Bạn đã tìm thấy một lỗi trong Json.NET. Nó chỉ phát sinh khi đối tượng của bạn được xây dựng với một hàm tạo tham số. Nếu tôi sửa đổi đối tượng của bạn để có một hàm tạo không tham số:

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

Sau đó Json.NET sẽ ném một cách chính xác JsonSerializationException.

Nguyên nhân của lỗi như sau. Khi tạo một đối tượng với một hàm tạo parameterless, Json.NET đầu tiên xây dựng đối tượng, sau đó điền nó với JsonSerializerInternalReader.PopulateObject(). Phương pháp này có những điều sau đây (giản thể) logic:

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

Như bạn có thể thấy, có là logic if (!finished) để xác minh rằng đối tượng đang thực sự đóng cửa.

Tuy nhiên, khi tạo một đối tượng với một constructor tham số, các tính chất được đọc trước khi đối tượng được xây dựng, sử dụng 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; 
    } 

Như bạn có thể thấy không có kiểm tra tương đương cho exit là sự thật.

Đã xảy ra sự cố Deserializing unclosed object succeeds when the object has a parameterized constructor. #1038 cho việc này.

+0

@ Łukasz - OK, tôi đã đi trước và báo cáo sự cố, [Deserializing đối tượng không được sắp xếp thành công khi đối tượng có một hàm tạo tham số. # 1038] (https://github.com/JamesNK/Newtonsoft.Json/issues/1038). – dbc

+1

Ồ, tôi đã được tiến hành, nhưng tôi sẽ dừng lại sau đó. Cảm ơn vì sự giúp đỡ –

Các vấn đề liên quan