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

PropertyFilter ignored if a diffed object is null #48

Open El-Gor-do opened 2 months ago

El-Gor-do commented 2 months ago

I am using SystemTextJson.JsonDiffPatch 2.0.0 on .Net 8.

Given this TestClass, I want diffs to include CompareMe and excludeIgnoreMe.

public class TestClass
{
    public int CompareMe { get; set; }
    public int IgnoreMe { get; set; }
}

When both left and right are not null, the diff correctly excludes IgnoreMe.

public void BothNotNull()
{
    TestClass left = new TestClass() { CompareMe = 1, IgnoreMe = 1 };
    TestClass right = new TestClass() { CompareMe = 2, IgnoreMe = 2 };

    string leftJson = JsonSerializer.Serialize(left);
    string rightJson = JsonSerializer.Serialize(right);

    JsonDiffOptions options = new JsonDiffOptions()
    {
        PropertyFilter = (prop, _) => !StringComparer.Ordinal.Equals(prop, nameof(TestClass.IgnoreMe)),
    };

    JsonNode? diff = JsonDiffPatcher.Diff(leftJson, rightJson, options);
    string diffJson = diff!.ToJsonString(); // {"CompareMe":[1,2]}
}

But if one of left and right is null then the JsonDiffOptions.PropertyFilter function doesn't run and the diff includes IgnoreMe.

public void LeftNull()
{
    TestClass? left = null;
    TestClass right = new TestClass() { CompareMe = 2, IgnoreMe = 2 };

    string leftJson = JsonSerializer.Serialize(left);
    string rightJson = JsonSerializer.Serialize(right);

    JsonDiffOptions options = new JsonDiffOptions()
    {
        PropertyFilter = (prop, _) => !StringComparer.Ordinal.Equals(prop, nameof(TestClass.IgnoreMe)),
    };

    JsonNode? diff = JsonDiffPatcher.Diff(leftJson, rightJson, options);
    string diffJson = diff!.ToJsonString(); // [null,{"CompareMe":2,"IgnoreMe":2}]
    // expected diffJson to be [null,{"CompareMe":2}]
}

public void RightNull()
{
    TestClass left = new TestClass() { CompareMe = 1, IgnoreMe = 1 };
    TestClass? right = null;

    string leftJson = JsonSerializer.Serialize(left);
    string rightJson = JsonSerializer.Serialize(right);

    JsonDiffOptions options = new JsonDiffOptions()
    {
        PropertyFilter = (prop, _) => !StringComparer.Ordinal.Equals(prop, nameof(TestClass.IgnoreMe)),
    };

    JsonNode? diff = JsonDiffPatcher.Diff(leftJson, rightJson, options);
    string diffJson = diff!.ToJsonString();  // [{"CompareMe":1,"IgnoreMe":1},null]
    // expected diffJson to be [{"CompareMe":1},null]
}