skip to Main Content

Is there any easy way to check if one JsonDocument has the same elements as another JsonDocument? I want to achieve something like b.Except(a).Any() for List.

Edit:
What I want is not DeepEquals as it compares absolutely everything and if there is the slightest mismatch it will give me false.
It will be a bit of c#-like pseudocode but consider this scenario:

b = {
  "prop1": 1,
  "prop2": "apple"
}
a = {
  "prop1": 1,
  "prop2": "apple",
  "prop3": "extra big"
}

I wan behavoiour like !b.Except(a).Any() because it would give me true in above scenario. DeepEquals will get me false.

2

Answers


  1. To achieve the behavior you’re looking for, where one JSON document (b) is a subset of another JSON document (a), you can iterate through the properties of both JsonDocument objects and compare them in a non-strict manner. You could use the following approach in C#:

    Parse both JSON documents into JsonElement objects.
    Loop through the properties of b and check if each property exists in a with the same value.
    If all properties in b exist in a and match, return true; otherwise, return false.
    Here’s an example:

    using System;
    using System.Text.Json;
    
    public class JsonSubsetComparison
    {
        public static bool IsSubset(JsonDocument subset, JsonDocument superset)
        {
            foreach (var property in subset.RootElement.EnumerateObject())
            {
                if (!superset.RootElement.TryGetProperty(property.Name, out var superProp) ||
                    !superProp.Equals(property.Value))
                {
                    return false; // Property missing or value mismatch
                }
            }
            return true; // All properties match
        }
    
        public static void Main()
        {
            var jsonA = "{"prop1": 1, "prop2": "apple", "prop3": "extra big"}";
            var jsonB = "{"prop1": 1, "prop2": "apple"}";
    
            using var docA = JsonDocument.Parse(jsonA);
            using var docB = JsonDocument.Parse(jsonB);
    
            bool result = IsSubset(docB, docA);
            Console.WriteLine(result); // Output: True
        }
    }
    
    Login or Signup to reply.
  2. gecapo’s answer almost got it right, but not quite:

    The problem is that superProp and property.Value are both JsonElement objects, and that struct neither implements IEquatable nor does it override the Equals method (see JsonElement.cs source code).

    Therefore superProp.Equals(property.Value) is basically a call to ValueType.Equals, which returns false (maybe because JsonElement has an internal reference to _parent, I don’t know).

    JsonElement does have a ValueEquals() method, but it only works for properties with JsonValueKind.String.

    The only way I could find would be to use GetRawText() and make a string comparison. I inserted a check of the ValueKind property though, because why bother retrieving string values of arbitrary length when a simple enum comparison could detect mismatches already.

    I’ve also converted the method to an extension and named it slightly differently, because I think docB.IsSubsetOf(docA) is much clearer than IsSubset(docB, docA).

    using System;
    using System.Text.Json;
    
    public static class JsonDocumentExtensions
    {
        public static bool IsSubsetOf(this JsonDocument subset, JsonDocument superset)
        {
            foreach (var subProp in subset.RootElement.EnumerateObject())
            {
                if (!superset.RootElement.TryGetProperty(subProp.Name, out var superPropValue) ||
                    superPropValue.ValueKind != subProp.Value.ValueKind ||
                    !superPropValue.GetRawText().Equals(subProp.Value.GetRawText()))
                {
                    return false; // Property missing or value mismatch
                }
            }
            return true; // All properties match
        }
    }
    
    public class JsonSubsetComparison
    {
        public static void Main()
        {
            var jsonA = "{"prop1": 1, "prop2": "apple", "prop3": "extra big"}";
            var jsonB = "{"prop1": 1, "prop2": "apple"}";
    
            using var docA = JsonDocument.Parse(jsonA);
            using var docB = JsonDocument.Parse(jsonB);
    
            bool result = docB.IsSubsetOf(docA);
            Console.WriteLine(result); // Output: True
        }
    }
    

    https://dotnetfiddle.net/I2AxoN

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search