6

I'm looking for a JSON paring library that supports comparing two JSON objects' structures, ignoring values, child order, and - if possible - optionally ignoring additional elements in the response; specifically for unit testing JSON returning from a web service against an expected structure. (I'd like to pass into the assert method a sample response and compare its structure to the actual response - instead of having to write asserts for each node. Getting different values back isn't a problem, as long as the structure is fine.)

Do any of the major JSON libraries support this? (This question is basically the same as Compare two JSON objects in Java, but I want the assert to ignore the values in my JSON structure, which might look like the example found on Wikipedia...)

Community
  • 1
  • 1
Christian
  • 6,070
  • 11
  • 53
  • 103
  • Define your own Comparator? – hd1 Mar 10 '14 at 18:35
  • Note that you need to define what it means for two JSON objects to be equivalent, given that key/value pairs are unordered. Eg, you could have `{key1:string,key2:[array stuff]}` and `{key3:[array stuff],key4:string}` -- are they the "same shape" or not? – Hot Licks Mar 10 '14 at 19:02
  • Hi @HotLicks, I'd say they are not, except if the keys are the same - as I don't care for the order of the elements... So, I'm looking to match key + type, but not the values... – Christian Mar 10 '14 at 22:14
  • It's a relatively easy job to create a recursive checker for this. Just take a value, do `instanceof` on it to see which type it is, route to array or map subroutine, have the subroutines iterate through the structures comparing counts, keys, and types. Recurisively call yourself if you encounter an array or map in the current array or map routine. Stop (and return false) when you get a mismatch, return true when there's nothing more to compare at a given level. – Hot Licks Mar 10 '14 at 22:18

2 Answers2

1

You may want to have a look at Guava and its Equivalence.

If for instance you use Jackson, you would write an Equivalence<JsonNode>, which you would customize for your needs.

Here is an example of such an Equivalence, which considers two JSON values equal if all numbers, recursively, are mathematically equal.

Usage: yourEquivalence.equivalent(node1, node2).

Another solution would be to write a POJO which serializes to the JSON you want and attempt to deserialize your JSON to said POJO. If deserialization fails your structure is wrong.

fge
  • 119,121
  • 33
  • 254
  • 329
0

I use a recursive function, if you want to ignore the values type you can change the last else condition content by a return true.

  • dict_var is the json you want to verify
  • schema is the schema that dict_var must follow

code:

def verify_config_parameters_structure(dict_var, schema):
try:
    # If it's a dictionary
    if isinstance(dict_var, dict):
        if isinstance(schema, dict):
            # Verify The object does not have more keys
            for k2, v2 in dict_var.items():
                if verify_config_parameters_structure(dict_var[k2], schema[k2]) is False:
                    return False
            # Verify The object does have at least the schema keys
            for k2, v2 in schema.items():
                if verify_config_parameters_structure(dict_var[k2], schema[k2]) is False:
                    return False
            return True
        else:
            return False
    # If it's a list
    elif isinstance(dict_var, list):
        if isinstance(schema, list):
            for item in dict_var:
                if verify_config_parameters_structure(item, schema[0]) is False:
                    return False
            return True
        else:
            return False
    # If it's a value
    else:
        if type(dict_var) is type(schema):
            return True
        else:
            return False
except:
    return False
Atto2O
  • 69
  • 1
  • 9