Here is what is returned from a API:
[
{
"id": "63c576504988e70xx",
"value": {
"text": "638dfbd58b3dde05xx"
},
"idCustomField": "62ed5fa43601c14xxx",
"idModel": "63c576504988e70249xxx",
"modelType": "card"
},
{
"id": "63c576504988e71xx",
"value": {
"number": "8"
},
"idCustomField": "62ed5fa43601c13xxx",
"idModel": "63c576504988e70249xxx",
"modelType": "card"
},
{
"id": "63c576504988e72xx",
"value": {
"text": "Dynamics"
},
"idCustomField": "62ed5fa43601c12xxx",
"idModel": "63c576504988e70249xxx",
"modelType": "card"
},
{
"id": "63c576504988e73xx",
"value": {
"number": "1"
},
"idCustomField": "62ed5fa43601c11xxx",
"idModel": "63c576504988e70249xxx",
"modelType": "card"
}
]
I don't really know how to properly write these so I used Microsoft auto generate and it gave me this:
{
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"type": "object",
"properties": {
"text": {
"type": "string"
}
}
},
"idCustomField": {
"type": "string"
},
"idModel": {
"type": "string"
},
"modelType": {
"type": "string"
}
},
"required": [
"id",
"value",
"idCustomField",
"idModel",
"modelType"
]
}
}
As you can see, the problem with the schema is that this part:
"value": {
"type": "object",
"properties": {
"text": {
"type": "string"
}
}
Value can have text or number but the auto generate only accounts for text. Additional concern is that sometimes this array will have only 1,2,3 or all 4 values in the array. How can I write a schema to account for these issues?
CodePudding user response:
This is according to https://json-schema.org/understanding-json-schema/reference/type.html:
{ "type": ["number", "string"] }
CodePudding user response:
There are a few ways this can be done. I'll present them in order of more preferred to less preferred.
The preferred option is to use oneOf
with required
. The following schema says that either "text" must be present or "number" must be present, but they can't both be present. This approach is preferred because it's straightforward to read and understand, isn't error prone, and produces pretty good validation error messaging.
{
"type": "object",
"properties": {
"text": { "type": "string" },
"number": { "type": "number" }
},
"oneOf": [
{ "required": ["text"] },
{ "required": ["number"] }
]
}
Another option is to use minProperties
and maxProperties
to assert that there is exactly one property present. When using this approach, you need to use "additionalProperties": false
or the presence of some other property, such as "foo", would pass. I consider this approach error prone because it's easy to forget additionalProperties
, but it's concise, easy to understand, and produces straightforward validation error messages except when there are no properties. In that case, it will tell you that there aren't enough properties, but won't tell you what properties are expected like the previous approach does.
{
"type": "object",
"properties": {
"text": { "type": "string" },
"number": { "type": "number" }
},
"additionalProperties": false,
"minProperties": 1,
"maxProperties": 1
}
Another approach you might see is to describe both versions of the object as separate schemas and switch off of them with oneOf
. Like the previous approach, this requires "additionalProperties": false
. I don't like this approach because it's unnecessarily verbose and has some duplication, but the benefit of this approach is that it's very straightforward to understand. Each schema in the oneOf
represents one version of what the object can be.
{
"oneOf": [
{
"type": "object",
"properties": {
"text": { "type": "string" }
},
"required": ["text"]
},
{
"type": "object",
"properties": {
"number": { "type": "number" }
},
"required": ["number"]
}
]
}