2013-10-17 8 views
10

Ad esempio uno schema per un file system, la directory contiene un elenco di file. Lo schema è costituito dalle specifiche del file, successivamente un sottotipo "immagine" e un altro "testo".Come dire allo strumento di convalida dello schema JSON di scegliere lo schema dal valore della proprietà?

Nella parte inferiore è presente lo schema della directory principale. La directory ha un contenuto di proprietà che è una matrice di elementi che dovrebbero essere sottotipi di file.

Fondamentalmente quello che sto cercando è un modo per dire al validatore di cercare il valore di un "$ ref" da una proprietà nell'oggetto json che viene convalidato.

Esempio 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 
     } 

    ] 
} 

La "pseudo" Schema nota che e definizioni "testo", "immagine" sono compresi nello stesso schema, ma potrebbero essere definiti altrove

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

Hai bisogno di chiarimenti. Si vuole far rispettare tutti gli elementi dei file in una directory con tutte le proprietà definite quando i dati della directory sono definiti (non in fase di progettazione), vero? – jruizaranguren

+0

Voglio che scelga la definizione corretta per un sottotipo di file dalla proprietà fileType – redben

risposta

9

Le parti di convalida di JSON Schema da sole non possono farlo: rappresentano una struttura fissa. Quello che vuoi richiede la risoluzione/gli schemi di riferimento alla validazione .

Tuttavia, si può esprimere questo utilizzando JSON Hyper-Schema, e un link rel="describedby":

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

Così qui, ci vuole il valore da "fileType" e lo usa per calcolare un legame con la relazione "describedby" - che significa "lo schema in questa posizione descrive anche i dati correnti".

Il problema è che la maggior parte dei validatori non prende in considerazione alcun collegamento (compresi quelli "descritti da"). Hai bisogno di trovare un "iper-validatore" che lo faccia.

UPDATE: la biblioteca tv4 ha aggiunto questo come una caratteristica

+0

Grazie, questo sembra fare il trucco, anche se devo ancora trovare il "hyper-validator" come dici tu, o roll mio! – redben

+0

Grazie a cloudfeet! Questa è la risposta che sto cercando.Descrittimi Per farmi mantenere uno schema disaccoppiato. Sto usando l'interpolazione per calcolare gli URI e presumo che possa anche usare l'interpolazione per il valore href di Relay descritto, come mostrato sopra. Grazie per aver postato una risposta! –

+0

Conoscete eventuali validatori, per JS, che supportano questo? –

3

Penso risposta cloudfeet è una soluzione valida. Puoi anche utilizzare lo stesso approccio described here.

Si avrebbe un tipo di oggetto file che potrebbe essere "anyOf" tutti i sottotipi che si desidera definire. Dovresti usare un enum per poter fare riferimento e validare contro ciascuno dei sottotipi.

Se gli schemi di sottotipi sono nello stesso file di JSON-Schema, non è necessario fare riferimento all'ur in modo esplicito con "$ ref". Un validatore draft4 corretto troverà il valore enum e proverà a convalidare tale "subschema" nell'albero Json-Schema.

In draft5 (in corso) è stata proposta una dichiarazione "switch" che consente di esprimere le alternative in modo più esplicito.

+1

Enum non è un'opzione dal momento che non lo so tutti i possibili sottotipi al momento dell'authoring. Conosco "immagine" e "testo" ma qualcuno potrebbe aggiungere un sottotipo di "file" nel proprio schema separato. In OOP che mapperebbe "file" si assocerebbe a un'interfaccia o una classe di API astratta. – redben

+0

Non vedo un problema con questo. Quello che estende l'interfaccia ha informazioni sui valori enum aggiuntivi, e può applicarli allo stesso modo in OOP, quello che estende ha conoscenza delle interfacce di base e anche delle estensioni. – jruizaranguren

+0

Non credo di aver capito. Se si utilizza enum per la proprietà (fileType) nei sottotipi, ok ma lo schema dovrebbe validare qualsiasi valore di "fileType" che non è desiderato ... D'altra parte "OOP quello che estende ha conoscenza delle interfacce di base e anche le estensioni ". No, non devi sapere quali altre estensioni sono per creare la tua estensione di una classe astratta di base o implementare un'interfaccia :) – redben

Problemi correlati