avian2 / jsonmerge

Merge a series of JSON documents.
MIT License
214 stars 25 forks source link

`AssertionError` at `assert head.val is resolved` #64

Open dotlambda opened 1 year ago

dotlambda commented 1 year ago

I'm trying to merge the following two files:

using the default strategy but am getting

Traceback (most recent call last):
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 386, in merge
    return merger.merge(base, head)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 341, in merge
    return walk.descend(schema, base, head).val
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 86, in descend
    rv = self.work(strategy, schema, *args, **opts)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 133, in work
    rv = strategy.merge(self, base, head, schema, objclass_menu=self.merger.objclass_menu, **kwargs)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/strategies.py", line 345, in merge
    base[k] = walk.descend(subschema, base.get(k), v)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 86, in descend
    rv = self.work(strategy, schema, *args, **opts)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 133, in work
    rv = strategy.merge(self, base, head, schema, objclass_menu=self.merger.objclass_menu, **kwargs)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/strategies.py", line 345, in merge
    base[k] = walk.descend(subschema, base.get(k), v)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 86, in descend
    rv = self.work(strategy, schema, *args, **opts)
  File "/nix/store/zj81jq5f04qcpa9ynal5m25hffja7adj-python3-3.10.12-env/lib/python3.10/site-packages/jsonmerge/__init__.py", line 131, in work
    assert head.val is resolved
AssertionError
avian2 commented 1 year ago

This might be caused by a bug in jsonschema related to resolving JSON pointers with empty strings.

Using jsonschema 4.18.4 and referencing 0.30.0:

from jsonschema.validators import RefResolver

doc = {"": 0}
resolver = RefResolver("urn:foo", doc)

with resolver.resolving("#/") as resolved:
    # resolves to {"": 0}, but should resolve to 0
    # as per https://datatracker.ietf.org/doc/html/rfc6901#section-6
    print(resolved)

The new referencing library that replaces the RefResolver works correctly however:

import referencing
import referencing.jsonschema

doc = {"": 0}

resource = referencing.Resource.from_contents(doc, default_specification=referencing.jsonschema.DRAFT4)
registry = referencing.Registry().with_resource("urn:foo", resource)
resolver = registry.resolver_with_root(resource)

resolved = resolver.lookup("#/")

# resolves to 0 correctly
print(resolved.contents)

With RefResolver being deprecated I'm not sure this will get fixed.

Unfortunately porting jsonmerge from RefResolver to referencing is not trivial either.