Как рекурсивно проверить схему JSON?

У меня есть схема JSON:

{
    "$schema": "http://myschema#",
    "type": "object",
    "properties": {
        "RBox": {
            "type": "array",
            "items": { "$ref": "#/definitions/rboxItem" },
            "uniqueItems": true
        },
        "TBox": {
            "type": "array",
            "items": { "$ref": "#/definitions/tboxItem" },
            "uniqueItems": true
        },
        "ABox": {
            "type": "array",
            "minItems": 1,
            "items": { "$ref": "#/definitions/aboxItem" },
            "uniqueItems": true
        }
    },
    "additionalProperties": false,
    "required": [ "ABox" ],
    "definitions": {
        "rboxItem": {
            "oneOf": [
                { "$ref": "#/definitions/inclusionRoleItem" },
                { "$ref": "#/definitions/transitiveRoleItem" }
            ]
        },
        "tboxItem": {
            "oneOf": [
                { "$ref": "#/definitions/inclusionConceptItem" },
                { "$ref": "#/definitions/equalConceptItem" }
            ]
        },
        "aboxItem": {
            "oneOf": [
                { "$ref": "#/definitions/ofTypeItem" },
                { "$ref": "#/definitions/inRelationItem" },
                { "$ref": "#/definitions/unequalItem" }
            ]
        },
        "inclusionRoleItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "inclusionR" ] },
                "included": { "$ref": "#/definitions/roleItem" },
                "including": { "$ref": "#/definitions/roleItem" }
            },
            "additionalProperties": false,
            "required": [ "op", "included", "including" ]
        },
        "transitiveRoleItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "transitive" ] },
                "arg": { "$ref": "#/definitions/roleItem" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg" ]
        },
        "inclusionConceptItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "inclusionT" ] },
                "included": { "$ref": "#/definitions/concept" },
                "including": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "included", "including" ]
        },
        "equalConceptItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "equal" ] },
                "arg1": { "$ref": "#/definitions/concept" },
                "arg2": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg1", "arg2" ]
        },
        "ofTypeItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "oftype" ] },
                "individual": { "$ref": "#/definitions/identifier" },
                "concept": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "individual", "concept" ]
        },
        "inRelationItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "inrelation" ] },
                "start": { "$ref": "#/definitions/identifier" },
                "end": { "$ref": "#/definitions/identifier" }
            },
            "additionalProperties": false,
            "required": [ "op", "start", "end" ]
        },
        "unequalItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "unequal" ] },
                "arg1": { "$ref": "#/definitions/identifier" },
                "arg2": { "$ref": "#/definitions/identifier" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg1", "arg2" ]
        },
        "roleItem": {
            "oneOf": [
                { "$ref": "#/definitions/roleName" },
                { "$ref": "#/definitions/inverseRoleName" }
            ]
        },
        "roleName": {
            "$ref": "#/definitions/identifier"
        },
        "inverseRoleName": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "inverse" ] },
                "arg": { "$ref": "#/definitions/roleName" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg" ]
        },
        "concept": {
            "oneOf": [
                { "$ref": "#/definitions/top" },
                { "$ref": "#/definitions/bottom" },
                { "$ref": "#/definitions/conceptName" },
                { "$ref": "#/definitions/negativeConceptName" },
                { "$ref": "#/definitions/andItem" },
                { "$ref": "#/definitions/orItem" },
                { "$ref": "#/definitions/existsItem" },
                { "$ref": "#/definitions/forallItem" },
                { "$ref": "#/definitions/atleastItem" },
                { "$ref": "#/definitions/atmostItem" }
            ]
        },
        "top": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "top" ] }
            },
            "additionalProperties": false,
            "required": [ "op" ]
        },
        "bottom": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "bottom" ] }
            },
            "additionalProperties": false,
            "required": [ "op" ]
        },
        "conceptName": {
            "$ref": "#/definitions/identifier"
        },
        "negativeConceptName": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "negation" ] },
                "arg": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg" ]
        },
        "andItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "and" ] },
                "arg1": { "$ref": "#/definitions/concept" },
                "arg2": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg1", "arg2" ]
        },
        "orItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "or" ] },
                "arg1": { "$ref": "#/definitions/concept" },
                "arg2": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "arg1", "arg2" ]
        },
        "existsItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "exists" ] },
                "role": { "$ref": "#/definitions/roleItem" },
                "concept": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "role", "concept" ]
        },
        "forallItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "forall" ] },
                "role": { "$ref": "#/definitions/roleItem" },
                "concept": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "role", "concept" ]
        },
        "atleastItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "atleast" ] },
                "number": {
                    "type": "integer",
                    "minimum": 1
                },
                "role": { "$ref": "#/definitions/roleItem" },
                "concept": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "number", "role", "concept" ]
        },
        "atmostItem": {
            "type": "object",
            "properties": {
                "op": { "enum": [ "atmost" ] },
                "number": {
                    "type": "integer",
                    "minimum": 1
                },
                "role": { "$ref": "#/definitions/roleItem" },
                "concept": { "$ref": "#/definitions/concept" }
            },
            "additionalProperties": false,
            "required": [ "op", "number", "role", "concept" ]
        },
        "identifier": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9]*$"
        }
    }
}

Схема имеет рекурсивные ссылки (например, concept может быть orItem, который, в свою очередь, содержит два concept. Когда я пытаюсь проверить после действительного json с использованием json-schema-validator я получаю fatal: validation loop: schema "#/definitions/concept/oneOf/0" visited twice for pointer "/ABox/0/concept/concept" of validated instance

JSON, который я пытаюсь проверить:

{
    "RBox": [],
    "TBox": [],
    "ABox": [{"op": "oftype", "individual": "a", "concept": {"op": "exists", "role": "r", "concept": "A"}}]
}

Что я делаю не так? Разве нельзя использовать схемы с рекурсивными определениями? Если да, то почему?


person user3820310    schedule 09.07.2014    source источник


Ответы (1)


Используйте tv4 вместо json-schema-validator.

person TiansHUo    schedule 06.08.2014