jsonref icon indicating copy to clipboard operation
jsonref copied to clipboard

jsonref removes existing key-values if reference is present

Open lucasrodes opened this issue 2 years ago • 2 comments

Given the schema:

{
  "foo": {
    "$ref": "#/def/url",
    "title": "something additional that should not be removed"
  },
  "def": {
      "url": {
        "pattern": "pattern",
        "type": "string"
      }
  }
}

When loading it with jsonref.loads, the key title is removed:

import jsonref

loaded = jsonref.loads('''
{
  "foo": {
    "$ref": "#/def/url",
    "title": "something additional that should not be removed"
  },
  "def": {
      "url": {
        "pattern": "pattern",
        "type": "string"
      }
  }
}
''')
loaded

Outputs:

{'foo': {'pattern': 'pattern', 'type': 'string'},
 'def': {'url': {'pattern': 'pattern', 'type': 'string'}}}

But I'd expect

{'foo': {'pattern': 'pattern', 'type': 'string', 'title': 'something additional that should not be removed'},
 'def': {'url': {'pattern': 'pattern', 'type': 'string'}}}

Is this expected?

Thanks!

lucasrodes avatar Aug 29 '23 13:08 lucasrodes

This is expected, and is how the json reference spec is written. If you desire the two objects (the referenced object and the json reference object) to be merged, there is the merge_props option. This option is outside the spec, and may be different between different libraries though. https://jsonref.readthedocs.io/en/latest/#the-replace-refs-function

EDIT: Here's some language from the JSON Ref 0.4 spec, which explains the default behavior.

Objects with a $ref property, such as { "$ref": <URI> }, are entirely replaced by the value pointed to by <URI>. This value is called the replacement-value. All other properties of an object containing a $ref key are ignored.

JSON Schema diverged from the original JSON Reference spec (especially in more recent iterations.) Using the mentioned merge_props option along with the jsonschema option in this library gets closer to the behavior JSON Schema uses with the $ref keyword, and may match for most basic cases.

gazpachoking avatar Aug 29 '23 13:08 gazpachoking

Shouldn't you be using this schema?

{
  "foo": {
    "allOf": [{"$ref": "#/def/url"}],
    "title": "something additional that should not be removed"
  },
  "def": {
      "url": {
        "pattern": "pattern",
        "type": "string"
      }
  }
}

dtheodor avatar Mar 25 '24 16:03 dtheodor