jsonref icon indicating copy to clipboard operation
jsonref copied to clipboard

Unresolvable JSON pointer with references/paths that contains ~1 and ~0

Open AlwaysBeCalm opened this issue 4 years ago • 2 comments

Hello there I'm working on a project for resolving the refs in open API documentation. when I resolve refs of this API: https://api.apis.guru/v2/specs/eos.local/1.0.0/openapi.json it shows me this exception: jsonref.JsonRefError: Unresolvable JSON pointer: '/paths/~1net~1status/post/responses/200/content/application~1json/schema/properties/last_handshake/properties/token' when I trace the path, it appeared to me that jsonref doesn't handle/resolve ~1 and ~0 properly.

here's a snippet of the code:

import json

import requests
import jsonref
api = 'https://api.apis.guru/v2/specs/eos.local/1.0.0/openapi.json'
data = requests.get(api).content
jsonref.JsonRef.replace_refs(
    json.loads(
        json.dumps(
            jsonref.loads(data), default=dict
        )
    )
)

and here's the entire exception:

Traceback (most recent call last):
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 252, in __subject__
    return self.cache
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 176, in __getattribute__
    return _oga(self, attr)
AttributeError: 'JsonRef' object has no attribute 'cache'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/jsonref.py", line 217, in resolve_pointer
    document = document[part]
KeyError: '~1net~1status'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/abdullah/Abdullah/coding/python/json/main_error.py", line 9, in <module>
    json.dumps(
  File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
    return cls(
  File "/usr/lib/python3.8/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.8/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 175, in __getattribute__
    return getattr(self.__subject__, attr)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 176, in __getattribute__
    return _oga(self, attr)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 134, in wrapper
    return method(self, *args, **kwargs)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 254, in __subject__
    self.cache = super(LazyProxy, self).__subject__
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 134, in wrapper
    return method(self, *args, **kwargs)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 240, in __subject__
    return self.callback()
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 134, in wrapper
    return method(self, *args, **kwargs)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/jsonref.py", line 174, in callback
    result = self.resolve_pointer(self.store[uri], fragment)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 134, in wrapper
    return method(self, *args, **kwargs)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/jsonref.py", line 219, in resolve_pointer
    self._error("Unresolvable JSON pointer: %r" % pointer, cause=e)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/proxytypes.py", line 134, in wrapper
    return method(self, *args, **kwargs)
  File "/home/abdullah/Abdullah/coding/python/json/venv/lib/python3.8/site-packages/jsonref.py", line 223, in _error
    raise JsonRefError(
jsonref.JsonRefError: Unresolvable JSON pointer: '/paths/~1net~1status/post/responses/200/content/application~1json/schema/properties/last_handshake/properties/token'

but when I use only the built-in JSON library, it works without any errors:

import json

import requests
import jsonref
api = 'https://api.apis.guru/v2/specs/eos.local/1.0.0/openapi.json'
data = requests.get(api).content
jsonref.JsonRef.replace_refs(
    json.loads(
        json.dumps(
            json.loads(data), default=dict
        )
    )
)

any help if anyone has faced this issue and solved it?

AlwaysBeCalm avatar Apr 11 '22 10:04 AlwaysBeCalm

We had a PR that fixed this, so it should be working on master branch. Looks like I never made a release with the fix though. I'll try to get around to that, sorry!

gazpachoking avatar Apr 15 '22 13:04 gazpachoking

Thanks, @gazpachoking for the response

I kinda did a workaround and replaced the / and ~ in the keys with _ like the solution here https://stackoverflow.com/a/2213368

also replaced the ~1 and ~0 from the values and it worked

import json
import jsonref
import requests

api = 'https://api.apis.guru/v2/specs/eos.local/1.0.0/openapi.json'
data = requests.get(api).text


def _replace_symbol_(schema_dict, symbol: str):
    return {f"{key.replace(symbol, '_') if symbol in key else key}": (
        _replace_symbol_(value, symbol) if isinstance(value, dict)
        else value) for key, value in schema_dict.items()}


schema = json.loads(data.replace("~1", "_").replace("~0", "_"))
schema = _replace_symbol_(schema, '/')
schema = _replace_symbol_(schema, '~')

jsonref.JsonRef.replace_refs(
    json.loads(
        json.dumps(
            jsonref.loads(schema), default=dict
        )
    )
)

AlwaysBeCalm avatar Apr 16 '22 04:04 AlwaysBeCalm

This was fixed in #29, and I finally made a v0.3 release that contains it.

gazpachoking avatar Oct 08 '22 20:10 gazpachoking