2017-09-10 3 views
0

Ich versuche JSON Schema zu erweitern, die eine Enumeration definiert:JSON Schema draft-04: Verlängerung für bestimmten „Enum“ Wert

{ 
    "$schema": "http://json-schema.org/draft-04/schema#", 
    "definitions": { 
    "objType": { 
     "enum": [ "A", "B" ] 
    }, 
    "baseType": { 
     "type": "object", 
     "properties": { 
     "category": { "$ref": "#/definitions/objType" } 
     } 
    } 
    }, 
    "properties": { 
    "A": { 
     "allOf": [ 
     { "$ref": "#/definitions/baseType" }, 
     /* how to restrict inherited `category' to "A"? */ 
     { /* properties specific to A */ } 
     ] 
    }, 
    "B": { 
     "allOf": [ 
     { "$ref": "#/definitions/baseType" }, 
     /* how to restrict inherited `category' to "B"? */ 
     { /* properties specific to B */ } 
     ] 
    } 
    } 
} 

Ich bin nicht sicher, wie man bestimmten Wert geerbt Enum Eigenschaft beschränken . Zum Beispiel:

// passes validation 
{ 
    "category": "A", 
    "prop_A": "blah A" 
} 

// fails because `prop_A' is not valid property for category "B" 
{ 
    "category": "B", 
    "prop_A": "blah A" 
} 

Danke.

Antwort

0

In der Building a mount point schema Beispiel tun sie dies ein wenig anders. Jede storage bezieht sich auf eine von mehreren Arten von Objekten:

"properties": { 
    "storage": { 
     "type": "object", 
     "oneOf": [ 
      { "$ref": "#/definitions/diskDevice" }, 
      { "$ref": "#/definitions/diskUUID" }, 
      { "$ref": "#/definitions/nfs" }, 
      { "$ref": "#/definitions/tmpfs" } 
     ] 
    }, 

und jede der Objekttypen enthält eine type ENUM mit einem anderen Wert. z.B. diskDevice gibt type auf diese Weise

"properties": { 
    "type": { "enum": [ "disk" ] }, 
    "device": { 
     "type": "string", 
     "pattern": "^/dev/[^/]+(/[^/]+)*$" 
    } 

während nfstype diese Weise

"properties": { 
    "type": { "enum": [ "nfs" ] }, 
    "remotePath": { 
     "type": "string", 
     "pattern": "^(/[^/]+)+$" 
    }, 

Vielleicht gibt man in diese Richtung Ihr Schema Refactoring in Erwägung ziehen könnte.

+0

Ja, ich habe dieses Beispiel gesehen. Wenn es keine andere Wahl gibt, werde ich das tun. Es bricht jedoch das Enum auf und streut es über das gesamte Schema, während es für Bugs anfällig wird, wenn zukünftige Änderungen kommen. –

+0

Vor einiger Zeit hatte ich ein ähnliches Problem im Zusammenhang mit einem Swagger-Schema und stieß auf https://gist.github.com/leedm777/5730877, aber in diesem Ansatz machen sie die Einschränkung * Der abgeleitete Typ darf keine definierten Eigenschaften neu definieren in irgendeinem seiner Basistypen *, die es hier möglicherweise ungeeignet machen, da ich denke, dass Ihr Ziel, "prop_A" zu haben, keine gültige Eigenschaft für die Kategorie "B" * ist, als eine Verletzung dieser Beschränkung betrachtet werden könnte. Ich würde auch gerne einen besseren Weg finden, aber noch nicht getan. – jq170727

0

JSON Schema ist eher ein Constraint-System als ein objektorientiertes System, daher passt "Vererbung" als Konzept nicht sehr gut. Weitere Informationen finden Sie unter https://github.com/json-schema-org/json-schema-org.github.io/issues/148.

In Ihrem Fall denke ich jedoch, dass das Constraint-System genau das ist, was Sie wollen. In einem Constraint-System können Sie immer weitere Constraints hinzufügen, aber Sie können sie niemals entfernen. Eine Enumeration auf eine Teilmenge ihrer "ererbten" Werte zu beschränken, ist also so einfach wie das Verwenden von "allOf", um eine Einschränkung einer einwertigen Enumeration über die ursprüngliche zweiwertige Enumeration hinzuzufügen.

{ 
    "$schema": "http://json-schema.org/draft-04/schema#", 
    "definitions": { 
    "objType": { 
     "enum": [ "A", "B" ] 
    }, 
    "baseType": { 
     "type": "object", 
     "properties": { 
     "category": { "$ref": "#/definitions/objType" } 
     } 
    } 
    }, 
    "properties": { 
    "A": { 
     "allOf": [ 
     { "$ref": "#/definitions/baseType" }, 
     { "objType": { "enum": [ "A" ] }. 
     { /* properties specific to A */ } 
     ] 
    }, 
    "B": { 
     "allOf": [ 
     { "$ref": "#/definitions/baseType" }, 
     { "objType": { "enum": [ "B" ] }. 
     { /* properties specific to B */ } 
     ] 
    } 
    } 
} 

Sie müssen nur weiter für jede Art von Eigentum an der Stelle, die Enum beschränken, wo es tatsächlich verwendet wird.