Repository: cwacek/python-jsonschema-objects

Issue:
oneOf example in README does not deserialize 
The README contains this example for `oneOf`:

```
{
  "title": "MultipleObjects",
  "id": "foo",
  "type": "object",
  "oneOf":[
    {"$ref": "#/definitions/ErrorResponse"},
    {"$ref": "#/definitions/VersionGetResponse"}
  ],
  "definitions": {
    "ErrorResponse": {
      "title": "Error Response",
      "id": "Error Response",
      "type": "object",
      "properties": {
        "message": {"type": "string"},
        "status": {"type": "integer"}
      },
      "required": ["message", "status"]
    },
    "VersionGetResponse": {
      "title": "Version Get Response",
      "type": "object",
      "properties": {
        "local": {"type": "boolean"},
        "version": {"type": "string"}
      },
      "required": ["version"]
    }
  }
}
```

I see this:

```
$ ipython
>>> import sys
>>> sys.version
'3.7.1 (default, Oct 22 2018, 11:21:55) \n[GCC 8.2.0]'
>>> import python_jsonschema_objects as pjs
>>> pjs.__version__
'0.3.5'

>>> builder = pjs.ObjectBuilder("oneOf-example.json")
>>> classes = builder.build_classes(named_only=True)

# create two test objects
>>> er = classes.ErrorResponse(message="Danger!", status=99)
>>> vgr = classes.VersionGetResponse(local=False, version="1.2.3")

# round-trip serialize-deserialize into named classes
>>> er2 = classes.ErrorResponse.from_json(er.serialize())
>>> vgr2 = classes.VersionGetResponse.from_json(vgr.serialize())

# round-trip serialize-deserialize into class defined with `oneOf`
>>> er2 = classes.Multipleobjects.from_json(er.serialize())
>>> vgr2 = classes.Multipleobjects.from_json(vgr.serialize())
Traceback (most recent call last):
  File "<ipython-input-10-53386795083b>", line 1, in <module>
    vgr2 = classes.Multipleobjects.from_json(vgr.serialize())
  File "/home/reece/.virtualenvs/default-3.7.1/lib/python3.7/site-packages/python_jsonschema_objects/classbuilder.py", line 116, in from_json
    obj.validate()
  File "/home/reece/.virtualenvs/default-3.7.1/lib/python3.7/site-packages/python_jsonschema_objects/classbuilder.py", line 272, in validate
    .format(missing, self.__class__.__name__))
ValidationError: '['message', 'status']' are required attributes for ErrorResponse

```

Swapping the order of the `ErrorResponse` and `VersionGetResponse` in the schema file does not change the outcome. Removing the `required` section from the `ErrorResponse` definition is sufficient to allow the above examples to succeed.

Discussion:

Patch:
diff --git a/python_jsonschema_objects/classbuilder.py b/python_jsonschema_objects/classbuilder.py
index 65dbfad..b455580 100644
--- a/python_jsonschema_objects/classbuilder.py
+++ b/python_jsonschema_objects/classbuilder.py
@@ -142,6 +142,7 @@ class ProtocolBase(collections.MutableMapping):
                 cls, klass))
             try:
                 obj = klass(**props)
+                obj.validate()
             except validators.ValidationError as e:
                 validation_errors.append((klass, e))
             else:
diff --git a/python_jsonschema_objects/wrapper_types.py b/python_jsonschema_objects/wrapper_types.py
index 9a8624a..c733700 100644
--- a/python_jsonschema_objects/wrapper_types.py
+++ b/python_jsonschema_objects/wrapper_types.py
@@ -125,7 +125,7 @@ class ArrayWrapper(collections.MutableSequence):
 
     def validate_uniqueness(self):
 
-        if getattr(self, 'uniqueItems', False) is True:
+        if getattr(self, 'uniqueItems', None) is not None:
             testset = set(self.data)
             if len(testset) != len(self.data):
                 raise ValidationError(


Test patch:
diff --git a/test/test_regression_156.py b/test/test_regression_156.py
new file mode 100644
index 0000000..8bb3af4
--- /dev/null
+++ b/test/test_regression_156.py
@@ -0,0 +1,18 @@
+import pytest  # noqa
+import python_jsonschema_objects as pjo
+
+
+def test_regression_156(markdown_examples):
+    builder = pjo.ObjectBuilder(markdown_examples['MultipleObjects'], resolved=markdown_examples)
+    classes = builder.build_classes(named_only=True)
+
+    er = classes.ErrorResponse(message="Danger!", status=99)
+    vgr = classes.VersionGetResponse(local=False, version="1.2.3")
+
+    # round-trip serialize-deserialize into named classes
+    classes.ErrorResponse.from_json(er.serialize())
+    classes.VersionGetResponse.from_json(vgr.serialize())
+
+    # round-trip serialize-deserialize into class defined with `oneOf`
+    classes.Multipleobjects.from_json(er.serialize())
+    classes.Multipleobjects.from_json(vgr.serialize())