2017-02-10 57 views
1

Отчасти это относится к проверке данных, но я боюсь, если это можно сделать с помощью проверки схемы json, которая будет лучше соответствовать моим потребностям. Мой вход:Проверка схемы Json для двоичных логических операций дерева

(1 or (1 and 0)) => true 

, которая становится объектом JSon:

[1, [1, 0]] 

Так проверки не должны давать никаких ошибок, но в данный момент моя схема не может работать ИЛИ случае правильно между вложенными данными.

{ 
    "allOf": [ 
    {"$ref": "#/definitions/_items"}, 
    { 
     "allOf": [ 
     {"$ref": "#/definitions/_or"}, 
     { 
      "items": { 
      "$ref": "#/definitions/_and" 
      } 
     } 
     ] 
    } 
    ], 
    "definitions": { 
    "_items": { 
     "minItems": 1, 
     "maxItems": 2, 
     "type": "array", 
     "items": { 
     "anyOf": [ 
      {"enum": [1,0]}, 
      {"$ref": "#/definitions/_items"} 
     ] 
     } 
    }, 
    "_or": { 
     "not": { 
     "type": "array", 
     "items": { 
      "not": { 
      "anyOf": [ 
       {"enum": [1]}, 
       {"$ref": "#/definitions/_items"} 
      ] 
      } 
     } 
     } 
    }, 
    "_and": { 
     "items": { 
     "anyOf": [ 
      {"enum": [1]}, 
      {"$ref": "#/definitions/_items"} 
     ] 
     } 
    } 
    } 
} 

Пользователи следующие данные по схеме:

[1,0] is valid, ok 
[1,1] is valid, ok 
[0,1] is valid, ok 
[0,0] not valid, ok 
[[1,1],1] valid, ok 
[[1,1],0] valid, ok 

но:

[[1,0],1] not valid, not ok! 
[[0,0],1] not valid, not ok! 

, потому что оба имеют 1 на оператора ИЛИ, поэтому левая сторона не имеет значения, если только отвечает _items определение ,

Итак, мой вопрос заключается в том, как изменить схему так, чтобы anyOf на стороне оператора OR было достаточно для корректного ввода?

Больше примеров, запрошенных @esp:

Мои примеры ввода по логическому выражению и соответствующих данных в формате JSON:

1 or (1 and 0)) => [1, [1, 0]] => true 
1 or (0 and 1)) => [1, [0, 1]] => true 
1 or (1 and 1)) => [1, [0, 0]] => true 
1 or (0 and 0)) => [1, [0, 0]] => true 
1 or (1)) => [1, [1]] => true 
1 or (0)) => [1, [0]] => true 
1 or 1 => [1, 1 => true 
1 or 0 => [1, 0] => true 
0 or 1 => [0, 1] => true 
0 or 0 => [0, 0] => false 

Я даю также несколько вложенных примеров на левой стороне, но не все, потому что комбинации получают быстро дикие:

(1 and 0) or (1 and 0)) => [[1, 0], [1, 0]] => false 
(0 and 0) or (0 and o)) => [[0, 0], [0, 0]] => false 
(1 and 1) or (1 and 0)) => [[1, 1], [1, 0]] => true 
(1 and 0) or (1 and 1)) => [[1, 0], [1, 1]] => true 
(1 and 1) or (1 and 1)) => [[1, 1], [1, 1]] => true 
+0

Вы можете определить все возможные входы и ожидаемые выходы? Некоторые из ваших примеров не соответствуют шаблону x или (y и z). – esp

+0

Также существует две проблемы: соответствует ли выражение шаблону и является ли оно истинным, поэтому вам, вероятно, нужны две схемы, а не одна, иначе как вы собираетесь различать не совпадающий шаблон и false? – esp

+0

@esp: Добавлены примеры.Таким образом, вход может быть: [p] или [q] или [p, q] или [p, [q]] или [[p], q] или [[p], [q]] ', слева и справа сторона двоичного элемента может быть числом 1,0 или множеством, содержащим хотя бы один подобный элемент, но не более двух. Это уже должно быть сделано с определением _items. – MarkokraM

ответ

0

Поскольку существует довольно мало перестановок, перечисляя возможные состояния делает схему проще и легче читать.

{ 
    "type": "array", 
    "minItems": 1, 
    "maxItems": 2, 
    "items": { 
    "anyOf": [ 
     { "enum": [0, 1] }, 
     { "enum": [[0], [1]] }, 
     { "enum": [[0, 0], [0, 1], [1, 0], [1, 1]] } 
    ] 
    }, 
    "allOf": [{ "$ref": "#/definitions/_or" }] 
    "definitions": { 
    "_or": { 
     "not": { 
     "items": { 
      "not": { "$ref": "#/definitions/_and" } 
     } 
     } 
    }, 
    "_and": { "enum": [1, [1], [1, 1]] } 
    } 
} 
+0

Справа. Двоичное дерево, с которым я сталкиваюсь, имеет неограниченные вложенные ветви, что является частью проблемы. Я думаю, что это требует рекурсивной проверки. Но, более строго говоря, о моем вопросе, ваш ответ, похоже, работает. – MarkokraM

+0

@MarkokraM Это все еще не ясно, если это рекурсивное дерево, есть ли ORs на уровнях, но последнее, и только последнее имеет AND или есть AND на всех уровнях, но первое. – esp

+0

Исправить. Операторы для разных двоичных узлов должны определяться вложенными объектами allOf, начиная с корня, так как на моем примере сейчас два уровня, но могут быть любыми. – MarkokraM

1

Используя проект-06 ключевые слова «содержит» (проверяет, что массив содержит по меньшей мере один элемент согласования схем) и «сопзЬ» (такой же, как «перечисление» с одним возможным значением):

{ 
    "contains": { "$ref": "#/definitions/one" }, 
    "definitions": { 
    "one": { 
     "anyOf": [ 
     { "const": 1 }, 
     { "$ref": "#/definitions/all" } 
     ] 
    }, 
    "all": { 
     "type": "array", 
     "items": { "$ref": "#/definitions/one" } 
    } 
    } 
} 

Как я писал в комментарии, эта схема только оценивает вашу логическую логику, она не подтверждает правильность дерева. Также он оценивает AND на всех уровнях, но первый.

Без проекта-06 ключевых слов, вы можете:

{ 
    "not": { "items": { "not": { "$ref": "#/definitions/one" } } }, 
    "definitions": { 
    "one": { 
     "anyOf": [ 
     { "enum": [1] }, 
     { "$ref": "#/definitions/all" } 
     ] 
    }, 
    "all": { 
     "type": "array", 
     "items": { "$ref": "#/definitions/one" } 
    } 
    } 
} 

Для подтверждения того, что структура дерева справедливо вам нужна другая простой схема:

{ 
    "type": "array", 
    "minItems": 1, 
    "maxItems": 2, 
    "items": { 
    "anyOf": [ 
     { "enum": [0, 1] }, 
     { "$ref": "#" } 
    ] 
    } 
} 

Вы можете присоединиться к этим двум схемам в один с " allOf ", но тогда вы не увидите разницы между деревом с недопустимой структурой и деревом, которое оценивает значение false.

+0

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

+0

Извините, я не понимаю. Вы можете объединить две схемы в одном, если это то, что вы имеете в виду. – esp

+0

Я пытаюсь перефразировать это лучше позже. Я подозреваю, что мой первоначальный вопрос был не слишком ясен из первых рук. – MarkokraM