recorrer objeto mostrar leer externo estructura ejemplos ejemplo datos crear con archivo json f# jsonschema

objeto - mostrar datos json javascript



¿Cómo puedo definir un esquema de Json que contenga definiciones, en código? (1)

Hackfest! :-)

De acuerdo con el código fuente , JSON.NET Schema simplemente no escribe una propiedad de definitions , al final de la historia. Entonces todo es inútil ... Casi.

Sin embargo, usa la propiedad de definitions en otro lugar. A saber: cuando se genera un esquema a partir de un tipo . Durante ese proceso, crea un JObject , JObject todos los esquemas en él y luego agrega ese objeto a JSchema.ExtensionData bajo la clave de definitions . Y al hacer referencia a un esquema desde otro lugar, el escritor de esquemas respetará ese objeto de definitions , si está presente, haciendo que todo funcione conjuntamente.

Entonces, armados con este conocimiento, podemos hackear nuestro camino hacia él:

let makeSchema = let addressSchema = JSchema() ... let definitions = JObject() :> JToken definitions.["address"] <- addressSchema |> JSchema.op_Implicit let schema = JSchema() schema.ExtensionData.["definitions"] <- definitions schema.Properties.Add("billing_address", addressSchema) schema.Properties.Add("shipping_address", addressSchema) schema

¡Y voilá! El esquema resultante ahora tiene un objeto de definitions , tal como los textos sagrados nos dicen que debería:

{ "definitions": { "address": { "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": [ "street_address", "city", "state" ] } }, "properties": { "billing_address": { "$ref": "#/definitions/address" }, "shipping_address": { "$ref": "#/definitions/address" } } }

Algunas notas:

  1. El nombre de las definitions no es especial desde el punto de vista de JSON.NET. Si cambia la línea schema.ExtensionData.["definitions"] a algo diferente, diga schema.ExtensionData.["xyz"] , seguirá funcionando, y todas las referencias apuntan a "#/xyz/address" .
  2. Todo este mecanismo, obviamente, es un hack Aparentemente no, según James Netwon-King . La idea clave parece ser que el JsonSchemaWriter podrá buscar cualquier mención previa de esquemas y usar referencias a ellos en otros lugares. Esto permite empujar los esquemas donde quiera y esperar que se haga referencia a ellos.
  3. Esa llamada op_Implicit allí es necesaria. JSchema no es un subtipo de JToken , por lo que no puedes JToken a definitions.["address"] JToken definitions.["address"] así, primero JToken convertirlo a JToken . Afortunadamente, hay un operador de conversión implícito definido para eso. Desafortunadamente, no es sencillo, parece que hay algo de magia sucediendo. Esto ocurre de manera transparente en C # (porque, ya sabes, no hay suficiente confusión), pero en F # tienes que llamarlo de manera explícita.

Estoy intentando replicar el siguiente ejemplo de Json Schema , definiendo el esquema en código usando Newtonsoft.Json.Schema :

{ "$schema": "http://json-schema.org/draft-04/schema#", "definitions": { "address": { "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"] } }, "type": "object", "properties": { "billing_address": { "$ref": "#/definitions/address" }, "shipping_address": { "$ref": "#/definitions/address" } }

Esto es lo más cercano que tengo hasta ahora. (El ejemplo está en F # pero podría estar en C #).

Código:

open Newtonsoft.Json.Schema open Newtonsoft.Json.Linq let makeSchema = let addressSchema = JSchema() addressSchema.Properties.Add("street_address", JSchema(Type = Nullable(JSchemaType.String))) addressSchema.Properties.Add("city", JSchema(Type = Nullable(JSchemaType.String))) addressSchema.Properties.Add("state", JSchema(Type = Nullable(JSchemaType.String))) addressSchema.Required.Add "street_address" addressSchema.Required.Add "city" addressSchema.Required.Add "state" let schema = JSchema() schema.Properties.Add("billing_address", addressSchema) schema.Properties.Add("shipping_address", addressSchema) schema

Salida:

{ "properties": { "billing_address": { "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": [ "street_address", "city", "state" ] }, "shipping_address": { "$ref": "#/properties/billing_address" } } }

Como puede ver, solo una de las dos direcciones se define utilizando una referencia a otro esquema, y ​​el esquema de la dirección está en "propiedades" en lugar de "definiciones". ¿Cuál es el truco para definir un esquema en "definiciones" y hacer referencia a él en otro lugar?