2013-10-17 1 views
10

Zum Beispiel ein Schema für ein Dateisystem, Verzeichnis enthält eine Liste von Dateien. Das Schema besteht aus der Spezifikation der Datei, als nächstes ein Untertyp "Bild" und ein anderer "Text".Wie erteile ich JSON-Schema-Validator, um Schema aus Eigenschaftswert auszuwählen?

Unten befindet sich das Hauptverzeichnisschema. Verzeichnis hat einen Eigenschafteninhalt, der ein Array von Elementen ist, die Untertypen von Dateien sein sollten.

Grundsätzlich ist das, was ich suche, eine Möglichkeit, dem Validator mitzuteilen, dass er den Wert eines "$ ref" aus einer Eigenschaft in dem zu validierenden JSON-Objekt nachschlagen soll. json

Beispiel:

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

    ] 
} 

Die "Pseudo" Schema zur Kenntnis, dass "Bild" und "Text" Definitionen werden in demselben Schema enthält, aber sie könnten an anderer Stelle

{ 
    "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 
       ] 
      } 
     } 
    } 
} 
definiert werden
+0

Bedarf Klärung. Sie möchten erzwingen, dass alle Dateien in einem Verzeichnis bestimmte Eigenschaften erfüllen, die definiert sind, wenn die Verzeichnisdaten definiert sind (nicht zur Entwurfszeit). Habe ich Recht? – jruizaranguren

+0

Ich möchte es die richtige Definition für eine Unterart der Datei aus der Eigenschaft fileType auswählen – redben

Antwort

9

Die Validierungsteile von JSON Schema allein können dies nicht - es stellt eine feste Struktur dar. Was Sie wollen, erfordert das Auflösen/Referenzieren von Schemas unter Validierung -Zeit.

jedoch können Sie diese mit JSON Hyper-Schema ausdrücken, und einen rel="describedby" Link:

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

Also hier ist es, den Wert von "fileType" nimmt und verwendet es einen Link mit Relation "describedby" zu berechnen - Das bedeutet "das Schema an diesem Ort beschreibt auch die aktuellen Daten".

Das Problem ist, dass die meisten Validatoren keine Kenntnis von irgendwelchen Links nehmen (einschließlich der "beschriebenen"). Sie müssen einen "Hyper-Validator" finden, der das tut.

UPDATE: die tv4 Bibliothek hat dies als eine Funktion hinzugefügt

+0

Danke, dies scheint den Trick zu tun, obwohl ich immer noch die "Hyper-Validator" wie Sie sagen, oder rollen Sie meine eigenen! – redben

+0

Danke Cloudfeet! Das ist die Antwort, nach der ich suche.configuredBy lasst mich ein entkoppeltes Schema beibehalten. Ich verwende Interpolation, um die URIs zu berechnen, und ich nehme an, dass ich auch Interpolation für den beschriebenenBy rels href-Wert verwenden kann, wie Sie oben zeigen. Danke für die Antwort! –

+0

Kennen Sie Validatoren für JS, die das unterstützen? –

3

Ich denke cloudfeet Antwort eine gültige Lösung. Sie können auch den gleichen Ansatz described here verwenden.

Sie hätten einen Dateiobjekttyp, der "anyOf" alle Subtypen sein könnte, die Sie definieren möchten. Sie würden eine Aufzählung verwenden, um auf jeden der Subtypen verweisen und validieren zu können.

Wenn sich die Schemas der Untertypen in derselben Json-Schema-Datei befinden, müssen Sie die URL nicht explizit mit "$ ref" referenzieren. Ein korrekter Draft4-Validator wird den Enum-Wert finden und versuchen, gegen dieses "Subschema" im Json-Schema-Baum zu validieren.

In draft5 (in Bearbeitung) wurde eine "switch" -Anweisung vorgeschlagen, die es erlaubt, Alternativen expliziter auszudrücken.

+1

Enum ist keine Option, da ich es nicht weiß alle möglichen Untertypen zum Zeitpunkt der Erstellung. Ich kenne "Bild" und "Text", aber jemand könnte einen Untertyp von "Datei" in ihrem eigenen separaten Schema hinzufügen. In OOP würde die Zuordnung "Datei" zu einer Schnittstelle oder einer abstrakten API-Klasse zugeordnet werden. – redben

+0

Ich sehe kein Problem damit. Derjenige, der das Interface erweitert, hat Informationen über die zusätzlichen Enum-Werte, und er kann sie auf dieselbe Weise in OOP erzwingen, wobei der eine das Wissen über Basisschnittstellen und auch die Erweiterungen besitzt. – jruizaranguren

+0

Ich glaube nicht, dass ich das verstehe. Wenn Sie enum für die Eigenschaft (fileType) in den Subtypes verwenden, ok, aber das Schema würde jeden Wert von "fileType" validieren, der nicht erwünscht ist ... Andererseits hat "OOP, der erweitert hat, Kenntnis von Basisschnittstellen und auch die Erweiterungen ". Nein, Sie müssen nicht wissen, was andere Erweiterungen sind, um Ihre eigene Erweiterung einer abstrakten Basisklasse zu erstellen oder eine Schnittstelle zu implementieren :) – redben

Verwandte Themen