Saltar al contenido

Esquema JSON condicional: requiere y no requiere

Solución:

Hay varias formas de lograr el efecto requerido incluso sin usar JSON Schema draft-07 si-entonces-si no.

operador lógico e implicación (borrador-04 y superior)

Una implicación lógica aquí: si hay “medio”, entonces se requiere “voluminoso” se puede traducir a “medio” no está presente O “voluminoso” es “obligatorio” (este último implica “medio” está presente) que se puede desarrollar más a fondo para “medio” no es obligatorio O “voluminoso” es “obligatorio” (ya que si “medio” está presente, cumplirá la condición de ser requerido). Vea el esquema a continuación:

"properties": {
  "smaller": {"type": "number"},
  "larger": { "type": "number" },
  "medium":{"type":"string"},
  "bulky":{"type":"string"}
},
"required":["smaller","larger"],
"anyOf" : [ 
  { 
    "not" : { "required" : ["medium"] }
  },
  {
    "required" : ["bulky"]
  }
],
"additionalProperties" : false

Consulte aquí para referencia:

Esquema JSON: válido si el objeto * no * contiene una propiedad en particular

http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.7

“anyOf” – OR lógico, “oneOf” – XOR, “allOf” – AND, “not” – negación, pero preste atención a las especificaciones:

Una instancia es válida con esta palabra clave si no se valida correctamente con el esquema definido por esta palabra clave.

draft-06 – dependencias + propertyNames

Lo mas obvio. No estoy seguro de si excluyó este en su pregunta, así que ponlo aquí por si acaso. Tenga en cuenta que, en lugar de “additionalProperties”, si simplemente desea limitar las claves válidas, se podría utilizar “propertyNames” (y es en realidad para lo que se agregó).

"properties": {
  "smaller": {"type": "number"},
  "larger": { "type": "number" },
  "medium":{"type":"string"},
  "bulky":{"type":"string"}
},
"required":["smaller","larger"],
"dependencies" : {
  "medium" : ["bulky"]
},
"propertyNames" : {
  "enum" : [
    "smaller",
    "larger",
    "medium",
    "bulky"
  ]
}

Consulte aquí para referencia: http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.7

Actualizar

Después de una aclaración en el comentario:

para el borrador-6 – aquí “no requiere” significa que si “medio” no existe, entonces “no debe estar presente” voluminoso

“no debe” significa evitar la presencia de objetos voluminosos.

Reformularé tu condición:

1. si existe “medio”, debe haber “voluminoso” -> ambas claves deben estar presentes al mismo tiempo

2. si “medio” no existe “voluminoso” no debe estar presente también -> ambas teclas no debe estar presente al mismo tiempo

¿Puede existir “bulky” y “medium” no existe?

No. Ver 2. Y viceversa (ver 1.). Igualdad booleana (complementaria al XOR lógico).

Por lo tanto, si existe “voluminoso”, significa que el “medio” debe estar siempre allí … Implica que ambos son requerido o ambos no debe ser requerido (o incluso permitido).

Dado que es draft-06, también puede usar “propertyNames” para definir nombres de propiedad permitidos (una especie de atajo a esta lógica).

operador lógico e implicación (borrador-06 y superior)

La operación lógica adecuada traducida a JSOn Schema se vería así:

"oneOf" : [
  { "required" : ["medium","bulky"] }, <== this schema is satisfied if both keys appear in validated instance
  {
    "allOf" : [   <== !medium ^ !bulky - due to how "not" works in schema context
      {"not" : { "required" : ["medium"] } },  
      {"not" : { "required" : ["bulky"] } },
    ]
  }
]

Un XOR – O (ambos obligatorios) O (no se requiere medio Y no se requiere voluminoso).

Tenga en cuenta que no estoy haciendo “no requerido” : [“medium”,”bulky”] } como cuando solo una de esas claves está presente, el esquema “requerido” fallaría, lo que significaría que “no” devolvería un resultado de validación exitoso. Hay que reformularlo utilizando las leyes de De Morgan:

"oneOf" : [
  { "required" : ["medium","bulky"] },
  {
    "not" : {   <=== !medium ^ !bulky = !(medium v bulky)
      "anyOf" : [
        { "required" : ["medium"] },
        { "required" : ["bulky"]  },
      ]
    }
  }
]

Sin embargo, el uso de “propertyNames” también funcionará. Consulte el siguiente esquema:

{
  "$schema": "http://json-schema.org/draft-06/schema#",
  "properties": {
    "smaller": {"type": "number"},
    "larger": { "type": "number" },
    "medium":{"type":"string"},
    "bulky":{"type":"string"}
  },
  "required":["smaller","larger"],
  "anyOf" : [ 
    { 
       "required" : ["medium","bulky"]
    },
    {
      "propertyNames" : {
        "enum" : [
          "smaller",
          "larger"
        ]
      },
    }
  ],
  "examples" : [
    {
      "smaller" : 1,
      "larger" : 2,


    },
    {
      "smaller" : 1,
      "larger" : 2,
      "bulky" : "test",
      "medium" : ""
    },
    {
      "smaller" : 1,
      "larger" : 2,

      "medium" : ""
    },
    {
      "smaller" : 1,
      "larger" : 2,
      "bulky" : "test",

    },
  ]
}

¿Responde a tu pregunta?

JSON Schema Draft-07 ha incluido estas nuevas palabras clave if, then y else que le permiten tener esquemas condicionales.

En este ejemplo:

  • Solo el foo la propiedad es requerida
  • Sin embargo, si foo se establece en "bar" entonces el bar la propiedad también se vuelve necesaria
var ajv = new Ajv({
  allErrors: true
});

var schema = {
  "properties": {
    "foo": {
      "type": "string"
    },
    "bar": {
      "type": "string"
    },

  },
  "required": ["foo"],
  "if": {
    "properties": {
      "foo": {
        "enum": ["bar"]
      }
    }
  },
  "then": {
    "required": ["bar"]
  }
}

var validate = ajv.compile(schema);

test({
  "foo": "bar",
  "bar": "baz"
}); // VALID

test({
  "foo": "xyz"
}); // VALID

test({
  "foo": "bar",
}); // NOT VALID


function test(data) {
  var valid = validate(data);
  if (valid) console.log('VALID', data);
  else console.log('NOT VALID', data);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ajv/6.5.5/ajv.min.js"></script>

Con suerte, esto tiene sentido y puede adaptar su código en consecuencia.

PD: en su esquema tiene el require propiedad que no estoy seguro de que sea una palabra clave de esquema JSON válida. Probablemente quisiste decir required en lugar de.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *