Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make sure item property in array is unique in Json Schema?

Given the following JSON schema, is it possible to indicate that the "name" property shall be unique (i.e. there should NOT be two items with the same "name" in the "elements" array.

{   "root": {     "type": "object",     "properties": {       "elements": {         "type": "array",         "minItems": 1,         "items": {           "type": "object",           "properties": {             "name": {               "type": "string",               "title": "Element Name",               "minLength": 3,             },             "url": {               "type": "string",               "title": "Some URL"             }           }         }       }     }   } } 

I tried to use the uniqueItems keyword but it seems it was designed for simple lists of values.

like image 623
begie Avatar asked Jul 15 '14 16:07

begie


People also ask

What is JSON schema additionalItems?

As of 2019-09 json-schema specification version, additionalProperties is a validation keyword for objects/documents, and additionalItems is a validation keyword for arrays. Follow this answer to receive notifications.

What is allOf in JSON schema?

By the definition of this keyword, it meant that the instance had to be valid against the current schema and all schemas specified in extends ; basically, draft v4's allOf is draft v3's extends .

Can JSON array have different types?

Arrays are used for ordered elements. In JSON, each element in an array may be of a different type.

How do you represent an array of objects in JSON?

A JSON array contains zero, one, or more ordered elements, separated by a comma. The JSON array is surrounded by square brackets [ ] . A JSON array is zero terminated, the first index of the array is zero (0). Therefore, the last index of the array is length - 1.


2 Answers

No, it is not possible. From the docs, json-schema: ...a JSON based format for defining the structure of JSON data.

It is quite limited for making data values validation because it is not the purpose of the standard. Many people have asked this before because it is common to request a kind of "unique Id" feature. Unfortunately for those who need it, json-schema does not provides you with that.

So if you want to ensure uniqueness your only option is to have "name" as property keys instead of property values.

like image 78
jruizaranguren Avatar answered Sep 23 '22 18:09

jruizaranguren


If refactoring the data structure is an option, the following approach may be helpful:

  • Replace the array by a map. This can easily be achieved by using an object with patternProperties. The pattern is a regular expression. Any object that matches the pattern will be validated against the schema of the pattern-property. A pattern matching any string >= 3 characters looks like this: "....*", but it seems that a trailing ".*" is always implied, so "..." works as well.
  • Adding additionalProperties:false is an additional step to enforce your constraint (minLength:3).
  • To enforce at least one element in your map (you were using minItems:1 for your array), replace minItems by minProperties.

... resulting in the schema below:

"root": {   "type": "object",    "properties": {     "elements": {       "type": "object",        "patternProperties": {         "...": {           "type": "object",            "properties": {             "url": {               "type": "string"             }           }         }       },        "additionalProperties": false,        "minProperties": 1     }   } } 

If a document like the following (excerpt) was matching your old schema,

"elements": [   {     "name": "abc",      "url": "http://myurl1"   },    {     "name": "def",      "url": "http://myurl2"   },    {     "name": "ghij",      "url": "http://myurlx"   } ] 

... a document like that (excerpt) will match the new schema:

"elements": {   "abc": {     "url": "http://myurl1"   },    "def": {     "url": "http://myurl2"   },    "ghij": {     "url": "http://myurlx"   } } 
like image 33
yaccob Avatar answered Sep 23 '22 18:09

yaccob