Skip to content

Commit

Permalink
bugfix: Fix #218 by serializing "null" for "null" types
Browse files Browse the repository at this point in the history
+ There were two sets of similar JSON serialization logic
  in place. This unifies them by just making all our custom objects
  call for_json() which already does the right thing.
+ The actual bug is fixed by permitting None values to serialize
  to JSON, iff the type of the object is "null"

Aside: I still don't understand why objects with _type_ null exist
       in the JSONSchema spec, but w/e.
  • Loading branch information
cwacek committed Sep 13, 2023
1 parent abf38dd commit 3d78861
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 18 deletions.
17 changes: 13 additions & 4 deletions python_jsonschema_objects/classbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ def as_dict(self):
out[prop] = [getattr(x, "for_json", lambda: x)() for x in propval]
elif isinstance(propval, (ProtocolBase, LiteralValue)):
out[prop] = propval.as_dict()
elif propval is not None:
elif (
propval is not None
or self.__propinfo__[prop].get("type", None) == "null"
):
out[prop] = propval

return out
Expand Down Expand Up @@ -151,9 +154,6 @@ def __new__(cls, **props):
obj = None
validation_errors = []
for klass in valid_types:
logger.debug(
util.lazy_format("Attempting to instantiate {0} as {1}", cls, klass)
)
try:
obj = klass(**props)
obj.validate()
Expand All @@ -171,6 +171,7 @@ def __new__(cls, **props):
return obj

def __init__(self, **props):
logger.debug(util.lazy_format("Creating '{0}'", self.__class__))
self._extended_properties = dict()
self._properties = dict(
zip(
Expand Down Expand Up @@ -649,6 +650,14 @@ def _build_object(self, nm, clsdata, parents, **kw):

# Set default value, even if None
if "default" in detail:
logger.debug(
util.lazy_format(
"Setting default for {0}.{1} to: {2}",
nm,
prop,
detail["default"],
)
)
defaults.add(prop)

if detail.get("type", None) == "object":
Expand Down
22 changes: 8 additions & 14 deletions python_jsonschema_objects/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,15 @@ def default(self, obj):
from python_jsonschema_objects import classbuilder
from python_jsonschema_objects import wrapper_types

if isinstance(obj, classbuilder.LiteralValue):
return obj._value
if isinstance(obj, wrapper_types.ArrayWrapper):
if isinstance(
obj,
(
wrapper_types.ArrayWrapper,
classbuilder.ProtocolBase,
classbuilder.LiteralValue,
),
):
return obj.for_json()
if isinstance(obj, classbuilder.ProtocolBase):
props = {}
for raw, trans in six.iteritems(obj.__prop_names__):
props[raw] = getattr(obj, trans)
if props[raw] is None:
del props[raw]
for raw, data in six.iteritems(obj._extended_properties):
props[raw] = data
if props[raw] is None:
del props[raw]
return props
else:
return json.JSONEncoder.default(self, obj)

Expand Down
57 changes: 57 additions & 0 deletions test/test_regression_218.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import pytest
import json
import python_jsonschema_objects as pjo

import logging

logging.basicConfig(level=logging.DEBUG)
logging.getLogger().setLevel(logging.DEBUG)

schema = """
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "schema.json",
"title":"Null Test",
"type": "object",
"$ref": "#/definitions/test",
"definitions": {
"test": {
"type": "object",
"properties": {
"name": {
"type": "string",
"default": "String"
},
"id": {
"type": "null",
"default": null
}
}
}
}
}
"""


@pytest.fixture
def schema_json():
return json.loads(schema)


@pytest.fixture
def ns(schema_json):
builder = pjo.ObjectBuilder(schema_json)
ns = builder.build_classes()
return ns


def test_defaults_serialize_for_nullable_types(ns):
logging.basicConfig(level=logging.DEBUG)
logging.getLogger().setLevel(logging.DEBUG)
thing1 = ns.NullTest()

serialized = thing1.as_dict()
print(serialized)
assert json.dumps(serialized) == """{"name": "String", "id": null}"""
serialized = thing1.serialize()
assert serialized == """{"name": "String", "id": null}"""

0 comments on commit 3d78861

Please sign in to comment.