xsd2json
xsd2json copied to clipboard
xs:choice and xs:sequence ignored in properties
The following schema element
<xs:complexType name="Resource">
<xs:annotation><xs:documentation>
Added in Version 1.2: INFO for diagnostics in several places
</xs:documentation></xs:annotation>
<xs:sequence>
<xs:element name="DESCRIPTION" type="anyTEXT" minOccurs="0"/>
<xs:element name="INFO" type="Info" minOccurs="0" maxOccurs="unbounded"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="COOSYS" type="CoordinateSystem"/><!-- Deprecated in V1.2 -->
<xs:element name="GROUP" type="Group" />
<xs:element name="PARAM" type="Param" />
</xs:choice>
</xs:complexType>
gives this JSON schema fragment:
"Resource": {
"properties": {
"name": {
"type": "string"
},
"DESCRIPTION": {
"$ref": "#/definitions/anyTEXT"
},
"INFO": {
"type": "array",
"items": {
"$ref": "#/definitions/Info"
},
"minItems": 0
}
}
We can see that children elements COOSYS/GROUP/PARAM are ignored. Therefore they are not validated although their schema is well defined in the schema.
The xs:choice
has not been implemented yet. I am currently thinking about an appropriate JSON Schema translation. It is not trivial :disappointed: Consider the following small XSD snippet:
<xs:sequence>
<xs:element name="owl" type="xs:string" />
<xs:choice>
<xs:element name="cat" type="xs:string" />
<xs:element name="dog" type="xs:string" />
<xs:element name="wolf" type="xs:string" />
</xs:choice>
</xs:sequence>
A possible direct translation would be:
{
"type": "object",
"properties": {
"owl": {
"type": "string"
},
"cat": {
"type": "string"
},
"dog": {
"type": "string"
},
"wolf": {
"type": "string"
}
},
"oneOf": [
{
"required": [ "cat" ]
},
{
"required": [ "dog" ]
},
{
"required": [ "wolf" ]
}
]
}
But what if we change one of the minOccurs
to 0
? This is perfectly valid in XML Schema and in some cases even useful:
<xs:sequence>
<xs:element name="owl" type="xs:string" />
<xs:choice>
<xs:element name="cat" type="xs:string" />
<xs:element name="dog" type="xs:string" minOccurs="0" />
<xs:element name="wolf" type="xs:string" />
</xs:choice>
</xs:sequence>
If we change the JSON Schema accordingly, the following is the result:
{
"type": "object",
"properties": {
"owl": {
"type": "string"
},
"cat": {
"type": "string"
},
"dog": {
"type": "string"
},
"wolf": {
"type": "string"
}
},
"oneOf": [
{
"required": [ "cat" ]
},
{
},
{
"required": [ "wolf" ]
}
]
}
But this is not the same as the given XML Schema! Although the object containing only a owl
property will pass the validation, the following does not:
{
"owl": "a",
"cat": "b",
}
The same applies for modelling the oneOf
with sub-schemas of the form { "properties": { "cat": {} } }
instead of { "required": [ "cat" ] }
, since the empty schema matches all objects and we can not use "additionalProperties": false
in the sub-schemas.
So we have to first think of an appropriate representation of these XML Schemas.
Following my understanding of XML schema, putting minOccurs="0" within a "choice " is an (legal) over-definition since each choice item has an implicit minOccurs="0" allowing it not to be chosen. My answer for this case would be to support the "choice" element, which is a basic feature of XSD but ignoring minOccurs="0" in this context.
@fnogatz is there an update on this issue? would appreciate a basic implementation with the first suggestion above.
+1 for a first pass implementation to this (have wrapped xsd2json in my own xs:choice implementation, but it'd be good to get one from source). Great work btw - this utility propelled me about 4 weeks forward on some work I'm doing
have wrapped xsd2json in my own xs:choice implementation
Is this anywhere available? It might be a good inspiration for native xsd2json support.
<xs:sequence>
<xs:element name="owl" type="xs:string" />
<xs:choice>
<xs:element name="cat" type="xs:string" />
<xs:element name="dog" type="xs:string" minOccurs="0" />
<xs:element name="wolf" type="xs:string" />
</xs:choice>
</xs:sequence>
could be translated to:
type: object
properties:
owl:
type: string
required: [owl]
oneOf:
- properties:
cat:
type: string
required: [cat]
- properties:
dog:
type: string
- properties:
wolf:
type: string
required: [wolf]