If you want two objects with the same elements but in a different order to compare equal, then the obvious thing to do is compare sorted copies of them - for instance, for the dictionaries represented by your JSON strings a and b:

import json

a = json.loads("""
{
    "errors": [
        {"error": "invalid", "field": "email"},
        {"error": "required", "field": "name"}
    ],
    "success": false
}
""")

b = json.loads("""
{
    "success": false,
    "errors": [
        {"error": "required", "field": "name"},
        {"error": "invalid", "field": "email"}
    ]
}
""")
>>> sorted(a.items()) == sorted(b.items())
False

... but that doesn't work, because in each case, the "errors" item of the top-level dict is a list with the same elements in a different order, and sorted() doesn't try to sort anything except the "top" level of an iterable.

To fix that, we can define an ordered function which will recursively sort any lists it finds (and convert dictionaries to lists of (key, value) pairs so that they're orderable):

def ordered(obj):
    if isinstance(obj, dict):
        return sorted((k, ordered(v)) for k, v in obj.items())
    if isinstance(obj, list):
        return sorted(ordered(x) for x in obj)
    else:
        return obj

If we apply this function to a and b, the results compare equal:

>>> ordered(a) == ordered(b)
True
Answer from Zero Piraeus on Stack Overflow
🌐
PyPI
pypi.org › project › json-schema-matcher
json-schema-matcher
JavaScript is disabled in your browser. Please enable JavaScript to proceed · A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, or try using a different browser
🌐
Readthedocs
jsonldschema.readthedocs.io › en › latest › semDiff › semDiffUsage.html
1.2.1. How to compare a set of JSON schemas: code example — jsonldschema 0.1 documentation
# In order to compare two set of schemas, you can use different classes depending # on whether your networks are resolved or not # First case scenario, your networks are not resolved # You will need to provide a dictionary of regex term/switch that will help # translate the schemas IDs into ...
🌐
Stack Overflow
stackoverflow.com › questions › 71654583 › compare-json-schema-not-based-on-contents
python - Compare json schema, not based on contents - Stack Overflow
But that being said you should not use a JSON file to compare the structure of your directories. This would work, but it's very slow as you already have all the information in main memory just to write it to a file and then read it again. That's not efficient at all. You should instead build a simple tree structure or use a dictionary to compare the files. ... In Python you could also use os.walk() as shown in this thread.
🌐
jsonschema
python-jsonschema.readthedocs.io › en › stable › validate
Schema Validation - jsonschema 4.26.0 documentation
A TypeChecker performs type checking for a Validator, converting between the defined JSON Schema types and some associated Python types or objects.
Top answer
1 of 12
225

If you want two objects with the same elements but in a different order to compare equal, then the obvious thing to do is compare sorted copies of them - for instance, for the dictionaries represented by your JSON strings a and b:

import json

a = json.loads("""
{
    "errors": [
        {"error": "invalid", "field": "email"},
        {"error": "required", "field": "name"}
    ],
    "success": false
}
""")

b = json.loads("""
{
    "success": false,
    "errors": [
        {"error": "required", "field": "name"},
        {"error": "invalid", "field": "email"}
    ]
}
""")
>>> sorted(a.items()) == sorted(b.items())
False

... but that doesn't work, because in each case, the "errors" item of the top-level dict is a list with the same elements in a different order, and sorted() doesn't try to sort anything except the "top" level of an iterable.

To fix that, we can define an ordered function which will recursively sort any lists it finds (and convert dictionaries to lists of (key, value) pairs so that they're orderable):

def ordered(obj):
    if isinstance(obj, dict):
        return sorted((k, ordered(v)) for k, v in obj.items())
    if isinstance(obj, list):
        return sorted(ordered(x) for x in obj)
    else:
        return obj

If we apply this function to a and b, the results compare equal:

>>> ordered(a) == ordered(b)
True
2 of 12
94

Another way could be to use json.dumps(X, sort_keys=True) option:

import json
a, b = json.dumps(a, sort_keys=True), json.dumps(b, sort_keys=True)
a == b # a normal string comparison

This works for nested dictionaries and lists.

🌐
Stack Overflow
stackoverflow.com › questions › 54121609 › comparing-two-json-schemas
python - Comparing two json schemas - Stack Overflow
January 10, 2019 - I'm looking to determine whether two highly nested json objects have the same schema. What I was thinking of doing was to get a list of all keys recursive and compare them. For example: def
🌐
JSON Diff
jsondiff.com
JSON Diff - The semantic JSON compare tool
Validate, format, and compare two JSON documents. See the differences between the objects instead of just the new lines and mixed up properties.
🌐
LinkedIn
linkedin.com › pulse › compare-json-find-diffs-eleonora-belova
Compare JSON and find Diffs - LinkedIn
July 27, 2021 - There are many tools and libraries available to test API responses against a JSON Schema. Since I use Python Framework (unittest) for API testing, the simplest way to validate an instance under a given schema is to use the validate() function.
Find elsewhere
Top answer
1 of 7
2

You're on the right track using ijson for streaming, but the issue is that pydantic expects the entire object at once, while ijson parses in a streaming manner. To validate incrementally without loading the entire JSON into memory, you can:

  1. Use a custom validator that incrementally checks each field as it arrives instead of waiting for the full object.
  2. Validate the a list items one by one instead of collecting them all in memory.

Instead of passing the entire JSON object to Pydantic at once, parse the JSON step-by-step and validate in parts.

import pydantic  # Pydantic V2
import ijson
import pathlib

class A(pydantic.BaseModel):
    i: int
    a: list[int] = []
    s: str

jsonpath = pathlib.Path("some.json")

errors = []
partial_data = {"i": None, "a": [], "s": None}

with jsonpath.open("rb") as file:
    for prefix, event, value in ijson.parse(file, use_float=True):
        if prefix == "i" and event == "number":
            partial_data["i"] = value
        elif prefix == "s" and event == "string":
            partial_data["s"] = value
        elif prefix.startswith("a.item") and event in {"number", "integer"}:
            try:
                # Validate individual array elements as they arrive
                int_value = int(value)
                A.model_validate({"a": [int_value]}, strict=True)
                partial_data["a"].append(int_value)
            except pydantic.ValidationError as e:
                errors.append(f"Error in 'a': {e.errors()}")

try:
    A.model_validate(partial_data, strict=True)
except pydantic.ValidationError as e:
    errors.append(e.errors())

print(errors if errors else "Validation passed")

This is the JSON Schema of some.json.

{
    "type": "object",
    "properties": {
        "id": {"type": "integer"},
        "name": {"type": "string"},
        "data": {
            "type": "array",
            "items": {"type": "integer"}
        }
    },
    "required": ["id", "name", "data"]
}
2 of 7
1

Pydantic comes with an experimental feature called "partial validation" that is designed for stream inputs.

See https://docs.pydantic.dev/latest/concepts/experimental/#partial-validation

You can create a Pydantic model from an existing JSON schema using datamodel-code-generator: https://koxudaxi.github.io/datamodel-code-generator/

Open issues I see right now with this method:

  1. Support is limited to specific types and the root must be a TypeAdapter instead of a BaseModel
  2. Unclear how to proceed after the inital validation step, with consecutive incoming data
🌐
Google Sites
sites.google.com › view › hadavgzxkm › python-compare-json-schema
Python Compare Json Schema
Remote debugging for table schema is written by name to code for a file. Four draft series to do now lets we should always have contributed with the developers. Url to use this allows formats and set the keys? Debug program easily understand the project and node in this bucket names to the two json. Information be used with python compare two json strings in the violation of json schema validation vocabulary or data.
🌐
PyPI
pypi.org › project › jsonschema
jsonschema - JSON Schema validation for Python
>>> validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema) >>> validate( ... instance={"name" : "Eggs", "price" : "Invalid"}, schema=schema, ... ) # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValidationError: 'Invalid' is not of type 'number' It can also be used from the command line by installing check-jsonschema.
      » pip install jsonschema
    
Published   Jan 07, 2026
Version   4.26.0
Top answer
1 of 2
2

The problem can be solved with littletree (I'm the author).

Assuming the original and modified data are stored as a nested dict in original and modified respectively

from littletree import Node

original_tree = Node.from_dict(original, identifier_name="name", children_name="tags")
modified_tree = Node.from_dict(modified, identifier_name="name", children_name="tags")

# Collect changes in a list
changes = []
for diff_node in original_tree.compare(modified_tree).iter_tree():
    diff_data = diff_node.data
    if not diff_data:
        continue  # Data was the same
    
    if "self" not in diff_data:
        changes.append({"tagpath": str(diff_node.path), "from": None, "to": "added"})
    elif "other" not in diff_data:
        changes.append({"tagpath": str(diff_node.path), "from": None, "to": "removed"})
    else:
        original_data, modified_data = diff_data["self"], diff_data["other"]
        for key, original_value in original_data.items():
            modified_value = modified_data[key]
            if original_value != modified_value:
                changes.append({"tagpath": f"{diff_node.path}.{key}",
                                "from": original_value,
                                "to": modified_value})

for change in changes:
    print(change)

The result looks like this:

{'tagpath': '/StackOverflow/FolderA/TagA.tooltip', 'from': 'This is tag a', 'to': 'This is tag a but changed'}
{'tagpath': '/StackOverflow/FolderA/TagA.value', 'from': 15, 'to': 16}
{'tagpath': '/StackOverflow/FolderA/TagB', 'from': None, 'to': 'removed'}
{'tagpath': '/StackOverflow/FolderA/TagC', 'from': None, 'to': 'added'}
2 of 2
1

May be some packages will be useful. If you don't want to use it, you can use iterator to instead for one by one.

from jsondiff import diff
json1 = {
    "name": "Bob",
    "age": 10,
    "sex": "male"
}
json2 = {
    "name": "Alice",
    "age": 10,
    "sex": "female"
}

difference1 = diff(json1, json2)
difference2 = diff(json2, json1)
print(difference1)
print(difference2)

result: {'name': 'Alice', 'sex': 'female'} {'name': 'Bob', 'sex': 'male'}

I think you can use this to construct your change log.

🌐
PyPI
pypi.org › project › jsonschema-diff
jsonschema-diff · PyPI
A library for comparing JSON schemas and displaying differences
      » pip install jsonschema-diff
    
Published   Feb 20, 2026
Version   0.1.9
🌐
jsonschema
python-jsonschema.readthedocs.io › en › latest › validate
Schema Validation - jsonschema 4.26.1.dev25+gad0a1b301 documentation
A TypeChecker performs type checking for a Validator, converting between the defined JSON Schema types and some associated Python types or objects.
🌐
Pydantic
docs.pydantic.dev › latest › concepts › json_schema
JSON Schema - Pydantic Validation
TypeAdapter.json_schema returns a jsonable dict of an adapted type's schema. ... These methods are not to be confused with BaseModel.model_dump_json and TypeAdapter.dump_json, which serialize instances of the model or adapted type, respectively. These methods return JSON strings. In comparison, BaseModel.model_json_schema and TypeAdapter.json_schema return a jsonable dict representing the JSON schema of the model or adapted type, respectively.
🌐
jsonschema
python-jsonschema.readthedocs.io
jsonschema 4.26.0 documentation
Be aware that the mere presence of these dependencies – or even the specification of format checks in a schema – do not activate format checks (as per the specification). Please read the format validation documentation for further details. If you have nox installed (perhaps via pipx install nox or your package manager), running nox in the directory of your source checkout will run jsonschema’s test suite on all of the versions of Python jsonschema supports.
🌐
PyPI
pypi.org › project › genson
genson · PyPI
Generate a schema and convert it directly to serialized JSON. ... Check for equality with another SchemaBuilder object. ... You can pass one schema directly to another to merge them. You can compare schema equality directly.
      » pip install genson
    
Published   May 15, 2024
Version   1.3.0
🌐
GitHub
github.com › getsentry › json-schema-diff
GitHub - getsentry/json-schema-diff: Diff changes between JSON schemas · GitHub
cargo install json-schema-diff cat schema-old.json schema-new.json # {"type": "string"} # {"type": "boolean"} cargo run --features=build-binary -- \ schema-old.json \ schema-new.json # {"path":"","change":{"TypeRemove":{"removed":"string"}},"is_breaking":true} # {"path":"","change":{"TypeAdd":{"added":"boolean"}},"is_breaking":false} Sentry uses this tool in sentry-kafka-schemas to annotate pull requests with breaking changes made to schema definitions. It invokes the CLI tool on the schema from master vs the schema in the PR, and post-processes the output using a Python script for human consumption.
Starred by 30 users
Forked by 7 users
Languages   Rust 99.1% | Shell 0.9%