23

I have a JSON Schema

{
    'description': 'TPNode',
    'type': 'object',
    'id': 'tp_node',
    'properties': {
        'selector': {
            'type': 'string',
            'required': true
        }, 
        'attributes': {
            'type': 'array',
            'items': {
                'name': 'string',
                'value': 'string'
            }
        },
        'children': {
            'type': 'array',
            'items': {
                'type': 'object',
                '$ref': '#'
            }
        },
        'events': {
            'type': 'array',
            'items': { 
                'type': 'object',
                'properties': {
                    'type': {
                        'type': 'string'
                    },
                    'handler': {
                        'type': 'object'
                    },
                    'dependencies': {
                        'type': 'array',
                        'items': {
                            'type': 'string'
                        }
                     }
                 }
            }
        }
    }
}

What I'm trying to express in the children property is that it's an array of objects with the same exact schema. Is this the correct way to describe it?

William
  • 1,517
  • 1
  • 12
  • 26

4 Answers4

25

Yes, your schema will work. The "$ref": "#" points back to the root of the schema document.

However, the "type": "object" is useless:

{
    'type': 'object',
    '$ref': '#'
}

If $ref is present, then all other keywords are ignored. It would be better to remove type from the #/properties/children/items schema.

krisanalfa
  • 6,268
  • 2
  • 29
  • 38
cloudfeet
  • 12,156
  • 1
  • 56
  • 57
22

Use the id of the schema you need to reference

'$ref': 'tp_node'

See here: http://json-schema.org/latest/json-schema-core.html#anchor30

Sergey Eremin
  • 10,994
  • 2
  • 38
  • 44
  • 3
    The solution proposed in the question (using `"$ref": "#"`) is actually better, because it works even if the schema is moved/renamed. With your solution, if you rename the schema then you need to alter a bunch of references which *could* be internal instead. – cloudfeet Dec 24 '13 at 01:17
  • 4
    This solution is preferable and should be the accepted one; in case of a change in the schema it breaks cleanly and obviously, as opposed to the more general one using `"$ref": "#"` with which changes are likely to produce harder to diagnose errors. – Peace Makes Plenty Jan 05 '14 at 09:48
  • Coming late into this, by pointing at itself will cause a circular reference error and I read somewhere it is not recommended to do so. But interesting enough I found this [github](https://github.com/json-schema-org/json-schema-spec/issues/279). I wish i can do that too, maybe it is the version of the schema I used (draft-6). – roger May 27 '19 at 12:45
9

Recursion example.

{
  "$schema": "http://json-schema.org/draft-07/schema#",

  "definitions": {
    "person": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "children": {
          "type": "array",
          "items": { "$ref": "#/definitions/person" },
          "default": []
        }
      }
    }
  },

  "type": "object",

  "properties": {
    "person": { "$ref": "#/definitions/person" }
  }
}
8

use definitions and $ref.

You can copy and paste the following schema to this online json/schema editor and check the results.

editor screenshot:

editor screenshot

schema code:

{
    "definitions": {
        "TPNode": {
            "title": "TPNode",
            "description": "TPNode",
            "type": "object",
            "properties": {
                "selector": {
                    "type": "string",
                    "required": true
                }, 
                "attributes": {
                    "type": "array",
                    "items": {
                        "title": "Attribute",
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": "string"
                            },
                            "value": {
                                "type": "string"
                            }
                        }
                    }
                },
                "children": {
                    "type": "array",
                    "items": {
                        "$ref": "#/definitions/TPNode"
                    }
                },
                "events": {
                    "type": "array",
                    "items": { 
                        "title": "Event",
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string"
                            },
                            "handler": {
                                "type": "object"
                            },
                            "dependencies": {
                                "type": "array",
                                "items": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "$ref": "#/definitions/TPNode"
}
krisanalfa
  • 6,268
  • 2
  • 29
  • 38
cuixiping
  • 24,167
  • 8
  • 82
  • 93