1

When using Python jsonschema it is possible to define schemas and instances that cannot be expressed in valid JSON.

>>> import jsonschema
>>> schema = {
...   "type": "object",
...   "properties": {"1": {}, 2:{}},
...   "additionalProperties": False
... }

Now

>>> jsonschema.validate({"1": "spam", 2: "eggs"}, schema)

does not raise an exception, while the code below fails:

>>> jsonschema.validate({1: "spam"}, schema)
Traceback (most recent call last):
   ...
jsonschema.exceptions.ValidationError: Additional properties are not allowed (1 was unexpected)

Failed validating 'additionalProperties' in schema:
    {'additionalProperties': False,
     'properties': {2: {}, '1': {}},
     'type': 'object'}

On instance:
    {1: 'spam'}

I'm a little confused here: the Python mapping {"1": "spam", 2: "eggs"} cannot be serialised in a valid JSON object, and the same applies to the schema mapping above. (In JSON objects are name/value mapping where the name has to be a string, and cannot be an integer or another data type).

Is this intended behaviour, i.e. the jsonschema semantics is extended to include more general python data types, or is the above use of schema invalid and should be flagged as an error by the jsonschema library? I read the docs, but was not able to find a mention to this point.

Stefano M
  • 4,267
  • 2
  • 27
  • 45
  • What happens if you try to serialise that into just a JSON string? Sounds like a JSON encoding issue rather than a JSON Schema issue. – Relequestual Dec 04 '18 at 13:43
  • @Relequestual In python `json.dumps({0: 0})` returns `'{"0": 0}'` (note the quote around the key) so that the roundtrip `json.loads(json.dumps({0: 0})) == {0: 0}` evaluates to `False`. This is expected behaviour, documented in the python docs [here](https://docs.python.org/3/library/json.html#json.dumps) – Stefano M Dec 04 '18 at 16:38
  • OK. I've pinged the module author (he is formally still part of the JSON Schema team, but doesn't drive much now), but I know he's been pretty busy recently. Sorry I don't know python. – Relequestual Dec 04 '18 at 16:39

1 Answers1

1

The Python jsonschema library, like most JSON Schema libraries, does not in fact operate on JSON. JSON is text. JSON Schema libraries operate generally on language-level objects, ones that JSON libraries deserialize into.

So yes, there are Python dicts you can construct that could never have come from JSON, like the one you have there.

The type though that jsonschema.validate takes is dict-that-came-from-JSON, so yes, if you gave it one that could never be JSON, you are going to get unexpected results (e.g., a current or future version of jsonschema is free to assume all keys are already strings, and you may see TypeErrors from places trying to perform string operations without converting first).

Julian
  • 3,375
  • 16
  • 27
  • To be more explicit: if I pass to `jsonschema.validate` a non-JSON dict (`loads(dumps(schema)) != schema`) results are undefined? Maybe this could be documented, or at least for trivial cases a `TypeError` raised. THX for the answer and the library. – Stefano M Dec 04 '18 at 16:53
  • Correct. In cases where there's a way to provide working behavior *outside* of the spec that doesn't affect the behavior *inside* of the spec (in this case the JSON spec), in general I've been happy to do so (and tried to do so, which is why e.g. support for specifying new types like `decimal.Decimal` or `YourNewFunType` exists), but that's the general answer in any other case. – Julian Dec 04 '18 at 20:45
  • I think this has come up a few times, so happy to document it. An issue ticket would be helpful if you don't mind filing it. And you're welcome! – Julian Dec 04 '18 at 20:45