weichch / system-text-json-jsondiffpatch

High-performance, low-allocating JSON object diff and patch extension for System.Text.Json. Support generating patch document in RFC 6902 JSON Patch format.
MIT License
102 stars 13 forks source link

Nullable properties #31

Closed WojciechNagorski closed 1 year ago

WojciechNagorski commented 2 years ago

I have type:

class test
{
    public int? ParentId { get; set; }
}

I've generated diff for the change:

{
  "ParentId": [
    1,
    ""
  ]
}

But then I'm not able to Patch object. I've got the exception:

System.Text.Json.JsonException: The JSON value could not be converted to System.Nullable`1[System.Int32]. Path: $.ParentId | LineNumber: 0 | BytePositionInLine: 73.
 ---> System.FormatException: Either the JSON value is not in a supported format, or is out of bounds for an Int32.
   at System.Text.Json.Utf8JsonReader.GetInt32WithQuotes()
   at System.Text.Json.Serialization.Converters.Int32Converter.ReadNumberWithCustomHandling(Utf8JsonReader& reader, JsonNumberHandling handling, JsonSerializerOptions options)
   at System.Text.Json.Serialization.Converters.NullableConverter`1.ReadNumberWithCustomHandling(Utf8JsonReader& reader, JsonNumberHandling numberHandling, JsonSerializerOptions options)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   --- End of inner exception stack trace ---
   at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
   at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
   at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo jsonTypeInfo, Nullable`1 actualByteCount)
   at System.Text.Json.JsonSerializer.ReadNode[TValue](JsonNode node, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Deserialize[TValue](JsonNode node, JsonSerializerOptions options)
   at Domain.Services.JsonTools.PatchObject[T](T object, JsonNode diff) in D:\work\inv\src\api\Domain.Services\JsonTools.cs:line 75
weichch commented 2 years ago

Looks like a bug to me in diff.

I can reproduce this using:

var left = JsonNode.Parse("{\"foo\":1}");
var right = JsonNode.Parse("{\"foo\":null}");

var diff = left.Diff(right);

JsonDiffPatcher.Patch(ref left, diff);

The diff generated is:

{"foo":[1,""]}

but it should be:

{"foo":[1,null]}
weichch commented 2 years ago

Should be fixed in 1.3.1-preview.2 now. I will leave this issue open until I can merge the PR.

WojciechNagorski commented 2 years ago

I've tested 1.3.1-preview.2 and everything looks great.

The diff of nullable properties works and I've checked the property filter and it works excellently.