2013-10-17 41 views
10

例如,文件系統的模式,目錄包含文件列表。該模式由文件規範,下一個子類型「圖像」和另一個「文本」組成。如何告訴JSON模式驗證器從屬性值中選擇模式?

底部有主目錄模式。目錄具有屬性內容,該內容是應該是文件的子類型的項目的數組。

基本上我正在尋找的是一種方法來告訴驗證器從被驗證的json對象的屬性中查找「$ ref」的值。

例JSON:

{ 
    "name":"A directory", 
    "content":[ 
     { 
      "fileType":"http://x.y.z/fs-schema.json#definitions/image", 
      "name":"an-image.png", 
      "width":1024, 
      "height":800 
     } 
     { 
      "fileType":"http://x.y.z/fs-schema.json#definitions/text", 
      "name":"readme.txt", 
      "lineCount":101 
     } 
     { 
      "fileType":"http://x.y.z/extended-fs-schema-video.json", 
      "name":"demo.mp4", 
      "hd":true 
     } 

    ] 
} 

「僞」模式注意「形象」和「文本」的定義都包含在相同的架構,但他們可能會在其他地方定義

{ 
    "id": "http://x.y.z/fs-schema.json", 
    "definitions": { 
     "file": { 
      "type": "object", 
      "properties": { 
       "name": { "type": "string" }, 
       "fileType": { 
        "type": "string", 
        "format": "uri" 
       } 
      } 
     }, 
     "image": { 
      "allOf": [ 
      { "$ref": "#definitions/file" }, 
      { 
       "properties": { 
        "width": { "type": "integer" }, 
        "height": { "type": "integer"} 
       } 
      } 
      ] 
     }, 
     "text": { 
      "allOf": [ 
      { "$ref": "#definitions/file" }, 
      { "properties": { "lineCount": { "type": "integer"}}} 
      ] 
     } 
    }, 
    "type": "object", 
    "properties": { 
     "name": { "type": "string"}, 
     "content": { 
      "type": "array", 
      "items": { 
       "allOf": [ 
       { "$ref": "#definitions/file" }, 
       { *"$refFromProperty"*: "fileType" } // the magic thing 
       ] 
      } 
     } 
    } 
} 
+0

需要澄清。你想強制目錄數據被定義時(而不是在設計時)定義的目錄中的所有文件項都滿足某些屬性,對嗎? – jruizaranguren

+0

我希望它從屬性fileType – redben

回答

9

單獨的JSON模式的驗證部分無法做到這一點 - 它代表了一個固定的結構。你想要什麼需要解決/參考模式驗證-時間。

但是,你可以表達這一點使用JSON的Hyper-架構和rel="describedby"鏈接:

{ 
    "title": "Directory entry", 
    "type": "object", 
    "properties": { 
     "fileType": {"type": "string", "format": "uri"} 
    }, 
    "links": [{ 
     "rel": "describedby", 
     "href": "{+fileType}" 
    }] 
} 

所以在這裏,它從"fileType"取值,並使用它來計算與關係「describedby」的鏈接 - 這意味着「這個位置的模式也描述了當前的數據」。

問題是,大多數驗證器不會注意到任何鏈接(包括「describeby」)。你需要找到一個「超驗證器」。

UPDATE:在tv4庫增添了這是一個功能

+0

中選擇一個子類型的文件的正確定義謝謝,這似乎是做伎倆,但我仍然必須找到「超驗證」,如你所說,或滾動我自己的! – redben

+0

感謝cloudfeet!這是我正在尋找的答案。讓我們保持一個分離的模式。我正在使用插值來計算URI,並且我假設我也可以使用插值來描述比較的rel值,如上所示。感謝您發佈答案! –

+0

你知道JS的驗證器支持嗎? –

3

我覺得cloudfeet答案是一個有效的解決方案。您也可以使用相同的方法described here

您將有一個文件對象類型,它可以是您想要定義的所有子類型的「anyOf」。您將使用枚舉爲了能夠引用和驗證每個子類型。

如果子類型模式在同一個Json-Schema文件中,則不需要使用「$ ref」顯式引用uri。一個正確的draft4驗證器將找到枚舉值,並將嘗試在Json-Schema樹中針對該「subschema」進行驗證。

draft5(進行中)中已經提出了「轉換」語句,這將允許以更明確的方式表示替代方案。

+1

Enum不是一個選項,因爲我不知道創作時所有可能的子類型。我知道「圖像」和「文字」,但有人可能會在他們自己的單獨模式中添加一個子文件類型的「文件」。在OOP中,映射「文件」將映射到接口或抽象API類。 – redben

+0

我沒有看到這個問題。擴展接口的那個具有額外枚舉值的信息,並且它可以在OOP中以相同方式強制執行它們,擴展了這些信息的是基本接口和擴展的知識。 – jruizaranguren

+0

我不認爲我理解。如果您在子類型中使用enum作爲(fileType)屬性,那麼確定,但是模式將驗證不需要的「fileType」的任何值......另一方面,「OOP擴展了對基本接口的瞭解,擴展名「。不,你不需要知道什麼其他的擴展可以讓你自己擴展一個基本的抽象類或者實現一個接口:) – redben