skip to Main Content

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?

2

Answers


  1. This is according to https://json-schema.org/understanding-json-schema/reference/type.html:

    { "type": ["number", "string"] }

    Login or Signup to reply.
  2. 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"]
        }
      ]
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search