2016-11-08 18 views
9
aşağıdaki Json Schema örnek çoğaltmak için çalışılıyor

, Newtonsoft.Json.Schema kullanarak kodunda şema tanımlayarak kodunda tanımlarını içeren bir Json Şeması, define: bende olarakNasıl yaparım

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

Bu kadar yakın şimdiye kadar. (Örnek F # ama sadece de C# olabilir.)

Kodu:

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 

Çıktı: Gördüğünüz gibi

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

, iki adresten tek tanımlanır Başka bir şemaya referans kullanarak ve adres şeması "tanımlar" yerine "özellikler" içinde bulunur. "Tanımlar" da bir şemayı tanımlamak ve başka bir yere atıfta bulunmanın yolu nedir?

cevap

8

Hackfest! :-)

source code'a göre, JSON.NET Schema sadece bir definitions mülkü, hikayenin sonunu yazmaz. Yani hepsi umutsuz ... Neredeyse. Bununla birlikte, başka bir yerde definitions özelliğini kullanır. Yani - when generating schema from a type. Bu işlem sırasında, bir JObject oluşturur, tüm şemaları içine ittirir vedefinitions anahtarının altına ekler. Ve bir şemaya başka bir yerden atıfta bulunurken, şema yazıcısı, varsa, definitions nesnesine saygılı olacak ve böylece her şeyin birlikte çalışmasını sağlayacaktır.

Yani, bu bilgiyle donanmış, bunu içine yolumuzu kesmek:

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 

Ve voila!

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

bir kaç not:

  1. definitions adı Json.NET bakış açısından özel değil sonuçlanan şema şimdi kutsal metinler bize olması gerektiği gibi, bir definitions nesne vardır görüş schema.ExtensionData.["definitions"] hattını schema.ExtensionData.["xyz"] numaralı farklı bir şeye değiştirirseniz, "#/xyz/address" işaretine işaret eden referanslarla çalışmaya devam edecektir.
  2. Bu mekanizma, açıkça, bir hack'idir Görünüşe göre, according to James Netwon-King. Temel içgörü, JsonSchemaWriter'un şemaların herhangi bir önceki bahsini arama ve diğer yerlerde referansları kullanabileceği gibi görünüyor. Bu, birinin sevdiği ve referans gösterilmesini beklediği yerlerde şemalar çizmesine izin verir.
  3. Bu op_Implicit numaralı telefonun aranması gerekmektedir. JSchema, JToken ürününün bir alt tipi değildir, bu yüzden definitions.["address"] ürününe bununla ilgili sıkışma yapamazsınız, bu dosyayı önce JToken numaralı telefona çevirmeniz gerekir. Neyse ki, bunun için tanımlanmış bir implicit cast operator var. Ne yazık ki, bu kolay değil, biraz büyü gibi görünüyor. Bu happens transparently in C# (çünkü bildiğiniz gibi, yeterince karışıklık olmadığı için), ancak F # 'da açıkça belirtmeniz gerekiyor.
+0

Çok teşekkür ederim! Buna yakındık ama op_Implicit bizi çizginin üzerine iten şeydi. Bir sorun kaydettim: https://github.com/JamesNK/Newtonsoft.Json.Schema/issues/60. Bunu test ettiğimde cevap olarak işaretleyeceğim. (Eminim iyi.; -) – Kit

+0

Bu yaklaşımı “gerçek dünya” kodumuzda kullandık ve bir çekicilik gibi çalıştı. Tekrar teşekkürler! – Kit

+0

Yardımdan memnun oldum –

İlgili konular