f# - How do I define a Json Schema containing definitions, in code -


i attempting replicate following json schema example, defining schema in code using 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" }   } 

this close i've got far. (example in f# might in c#.)

code:

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 

output:

{   "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"     }   } } 

as can see, 1 of 2 addresses defined using reference schema, , address schema in "properties" rather "definitions". what's trick defining schema in "definitions" , referencing elsewhere?

hackfest! :-)

according source code, json.net schema doesn't write definitions property, end of story. it's hopeless... almost.

it use definitions property in place, however. namely - when generating schema type. during process, creates jobject, pushes schemas it, , adds object jschema.extensiondata under definitions key. , when referencing schema place, schema writer respect definitions object, if present, making whole thing work together.

so, armed knowledge, can hack our way it:

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 

and voila! resulting schema has definitions object, sacred texts tell should:

{   "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"     }   } } 

a few notes:

  1. the definitions name not special json.net's point of view. if change line schema.extensiondata.["definitions"] different, schema.extensiondata.["xyz"], still work, references pointing "#/xyz/address".
  2. this whole mechanism, obviously, hack apparently not, according james netwon-king. key insight seems jsonschemawriter able lookup previous mentions of schemas , use references them in other places. allows 1 shove schemas wherever 1 likes , expect them referenced.
  3. that op_implicit call in there necessary. jschema not subtype of jtoken, can't jam definitions.["address"] that, have convert jtoken first. fortunately, there implicit cast operator defined that. unfortunately, it's not straightforward, there seems magic going on. happens transparently in c# (because, know, there not enough confusion is), in f# have call explicitly.

Comments

Popular posts from this blog

php - How to add and update images or image url in Volusion using Volusion API -

javascript - jQuery UI Splitter/Resizable for unlimited amount of columns -

javascript - IE9 error '$'is not defined -