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:
- El nombre de las
definitions
no es especial desde el punto de vista de JSON.NET. Si cambia la líneaschema.ExtensionData.["definitions"]
a algo diferente, digaschema.ExtensionData.["xyz"]
, seguirá funcionando, y todas las referencias apuntan a"#/xyz/address"
. -
Todo este mecanismo, obviamente, es un hackAparentemente no, según James Netwon-King . La idea clave parece ser que elJsonSchemaWriter
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. - Esa llamada
op_Implicit
allí es necesaria.JSchema
no es un subtipo deJToken
, por lo que no puedesJToken
adefinitions.["address"]
JToken
definitions.["address"]
así, primeroJToken
convertirlo aJToken
. 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?