How do I do a nested list (array) of schema references in json schema that isn't a dictionary

xamox picture xamox · Mar 8, 2016 · Viewed 7.8k times · Source

So I have a similiar question (see: How do I do a nested list (array) of schema references in json schema), but now my structure is changed a little and can't seem to get it to validate.

data = {
  'VIN': '1234567',
  'Vehicle color': blue,
  'inspections': [
      {'expected': 'MVA',
      'found': 0.0,
      'inspection': 'Fascia',
      'location': 'rear_left',
      'state': None},
      {'expected': 'MVA',
      'found': 0.0,
      'inspection': 'Fascia',
      'location': 'rear_right',
      'state': None},
      {'expected': 'UNKNOWN',
      'found': 'CPW7',
      'inspection': 'liftGateHandle',
      'location': 'center_bottom',
      'state': True},
      {'expected': 'tinted',
      'found': 'tinted',
      'inspection': 'rearWindowtint',
      'location': 'center_top',
      'state': True},
  ],
  'model': 'racecar',
  'timestamp': '2016-03-03 01:44:00.616000'
 }

I'm using the same schema as listed in the previous link here:

schema = {
    "$schema": "http://json-schema.org/draft-04/schema#",
    "definitions": {
        "inspection": {
            "type": "object",
            "properties": {
                "expected" : { "type" : "string" },
                "found": { "type" : "string"},
                "state" : { "type" : "string" },
                "image" : { "type" : "string"}
            },
            "required": ["state", "image","expected"]
        },
    },
    "type" : "object",
    "properties" : {
        "VIN" : { "type" : "string" },
        "timestamp" : { "type" : "string"},
        "model" : { "type" : "string"},
        "inspections" : { 
            "type" : "array",
            "items" : {
                "type" : "object",
                "maxProperties": 1,
                "minProperties": 1,
                "additionalProperties" : {
                    "$ref" : "#/definitions/inspection"
                }
            }
        }
    },
    "required": ["VIN", "timestamp", "model", "inspections"]
}

I've tried making the definition use array instead of object but no luck I get the following error when trying to validate:

ValidationError: 'black' is not of type 'object'

Failed validating 'type' in schema['properties']['inspections']['items']['additionalProperties']:
    {'properties': {'expected': {'type': 'string'},
                    'found': {'type': 'string'},
                    'image': {'type': 'string'},
                    'state': {'enum': [0, 1]}},
     'required': ['state', 'image', 'expected'],
     'type': 'object'}

On instance['inspections'][0]['expected']:
    'black'

Answer

jruizaranguren picture jruizaranguren · Mar 9, 2016

The problem lies in the same misunderstanding of the previous question. In the specification of the inspections you have:

 "inspections" : { 
            "type" : "array",
            "items" : {
                "type" : "object",
                "maxProperties": 1,
                "minProperties": 1,
                "additionalProperties" : {
                    "$ref" : "#/definitions/inspection"
                }
            }
        }

This means that inspections must be an array, and its items must be objects with a single property. That property must comply with #/definitions/inspection schema.

According to your current schema, inspections items should be like:

"inspections" : [{
        "anyKeyIsValidHere" : {
            "expected" : "MVA",
            "found" : 0.0,
            "inspection" : "Fascia",
            "location" : "rear_left",
            "state" : 0
        }
    }
]

Hence, in this case, reversely than in your previous question, your inspections item should simply be like this:

"inspections" : {
    "type" : "array",
    "items" : {
        "$ref" : "#/definitions/inspection"
    }
}

A final advice. Try to build the schemas step by step, ensuring that each desired constraint is properly enforced. That also helps to make more focused SO questions.