Newtonsoft.Json parsing invalid json

I had a strange problem: this line {"text":"s","cursorPosition":189,"dataSource":"json_northwind", , which is not a valid json, is still successfully parsed.

this is the class:

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

Here is a test that surprisingly succeeds:

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

Does the library have some weakened parsing rules, or maybe this is a mistake? I am library version 9.0.1

+5
source share
1 answer

Update

Problem Removing the deserialization of a closed object succeeds when the object has a parameterized constructor. # 1038 was open on this subject. It has been fixed in Json.NET release 10.0.1 in changelog 0721bd4 .

Original answer

You found a bug in Json.NET. This only happens when your object is constructed with a parameterized constructor. If I modify my object to have a non-parameterized constructor:

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

Then Json.NET correctly throws a JsonSerializationException .

The cause of the error is as follows. When creating an object with a constructor without parameters, Json.NET first creates the object and then populates it with JsonSerializerInternalReader.PopulateObject() . This method has the following (simplified) 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; } 

As you can see, there is if (!finished) logic to verify that the object is actually closed.

However, when creating an object with a parameterized constructor, the properties are read before building the object using 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; } 

As you can see, there is no equivalent check for exit being true.

Problem Removing the deserialization of a closed object succeeds when the object has a parameterized constructor. # 1038 for this.

+5
source

Source: https://habr.com/ru/post/1257931/


All Articles