Как заставить имя ключа объекта в массиве - PullRequest
0 голосов
/ 09 мая 2018

Я использую YAML для разметки некоторых формул и использую схему JSON для предоставления справочной схемы.Примером YAML может быть:

formula: # equates to '5 + (3 - 2)'
  add:
    - 5
    - subtract: [3, 2]

Хотя я выяснил, как заставить непосредственный дочерний объект формулы (в данном примере "add") иметь правильное имя и тип ключа (используя"oneOf" массив "required" с).Я не уверен, как обеспечить, чтобы объект массива ("subtract") также использовал определенные имена ключей.

Пока что я могу обеспечить тип, используя следующее.Но с помощью этого метода, если используемый объект соответствует вычитанию тип , ему разрешается любое имя ключа, оно не ограничивается subtract:

"definitions: {
    "add": {
        "type": "array",
        "minItems": 2,
        "items": {
            "anyOf": [
                { "$ref": "#/definitions/value"}, # value type is an integer which allows for the shown scalar array elements
                { "$ref": "#/definitions/subtract" }
                // other operation types
            ]
        }
    },
    "subtract": {
        "type": "array",
        "minItems": 2,
        "maxItems": 2,
        "items": {
            "anyOf": [
                { "$ref": "#/definitions/value"},
                { "$ref": "#/definitions/add" }
                // other operation types
            ]
        }
    }
    // other operation types
}

Как я могуввести такое ограничение, чтобы ключи объектов в массиве соответствовали определенным именам, но в то же время позволяли скалярные элементы?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

Какая увлекательная проблема! Эта удивительно лаконичная схема может выражать любое выражение.

{
  "type": ["object", "number"],
  "propertyNames": { "enum": ["add", "subtract", "multiply", "divide"] },
  "patternProperties": {
    ".*": {
      "type": "array",
      "minItems": 2,
      "items": { "$ref": "#" }
    }
  }
}
0 голосов
/ 11 мая 2018

В итоге я расширил идею, которую я уже использовал, с массивом "oneOf", равным "required", добавив "anyOf".

.

Таким образом, схема оператора теперь:

"definitions": {
    "add": {
        "type": "array",
        "minItems": 2,
        "items": {
            "anyOf": [
                { "$ref": "#/definitions/literal" }, // equates to a simple YAML scalar
                { "$ref": "#/definitions/constant" },
                { "$ref": "#/definitions/variable" },
                {
                    "type": "object",
                    "oneOf": [
                        { "required": ["add"] },
                        { "required": ["subtract"] }
                        // more operator names
                    ],
                    "properties": {
                        "add": { "$ref": "#/definitions/add" },
                        "subtract": { "$ref": "#/definitions/subtract" }
                        // more operator type references
                    }
                }
            ]
        }
    },
    // more definitions
}

Это может быть реорганизовано для чего-то более удобного для разных операторов, например:

"definitions": {
    "operands": {
        "literal": { "type": "number" }, // equates to a simple YAML scalar
        "constant": {
            "type": "object",
            "properties": {
                "value": { "type": "number" }
            },
            "required": [ "value" ]
        },
        "variable": {
            "type": "object",
            "properties": {
                "name": { type": "string" },
                "type": { "type": "string" }
            },
            "required": [ "name", "type" ]
        }
    }
    "operators": {
        "add": {
            "type": "array",
            "minItems": 2,
            "items": { "$ref": "#/definitions/anyOperandsOrOperators" }
        },
        "subtract": {
            "type": "array",
            "minItems": 2,
            "maxItems": 2,
            "items": { "$ref": "#/definitions/anyOperandsOrOperators" }
        }
        // more operator types
    },
    "anyOperator": {
        "type": "object",
        "oneOf": [
            { "required": ["add"] },
            { "required": ["subtract"] }
            // more operator names
        ],
        "properties": {
            "add": { "$ref": "#/definitions/operators/add" },
            "subtract": { "$ref": "#/definitions/operators/subtract" }
            // more operator type references
        }
    },
    "anyOperandsOrOperators":
    {
        "anyOf": [
            { "$ref": "#/definitions/operands/literal" },
            { "$ref": "#/definitions/operands/constant" },
            { "$ref": "#/definitions/operands/variable" },
            { "$ref": "#/definitions/anyOperator"}
        ]
    }
}

А это значит, что YAML для оператора может выглядеть следующим образом

                    \/mapping   \/mapping
add:[ 5, subtract:[ *constantA, *variableB ] ]
scalar^  ^mapping with specific name
0 голосов
/ 09 мая 2018

Звучит так, как будто вам нужны рекурсивные ссылки.

Создав новое определение, которое представляет собой oneOf операции и value, которые затем разрешают элементы, которые затем ссылаются на новое определение, вы получаете рекурсивные ссылки.

"definitions: {
    "add": {
        "type": "array",
        "minItems": 2,
        "items": { "$ref": "#/definitions/operations_or_values"},
    },
    "subtract": {
        "type": "array",
        "minItems": 2,
        "maxItems": 2,
        "items": { "$ref": "#/definitions/operations_or_values"},
    }
    // other operation types
    "operations_or_values": {
      "anyOf": [
        { "$ref": "#definitions/add" },
        { "$ref": "#definitions/subtract" },
        { "$ref": "#definitions/value" },                 # value type is an integer which allows for the shown scalar array elements
        { "$ref": "#definitions/[OTHERS]" },
      ]
    }
}

У меня не было времени проверить это, но я верю, что это будет или будет близко к тому, что вам нужно. Дайте мне знать, если это не сработает. Возможно, я не полностью понял вопрос.

...