Maciek, there might be an issue with your schema. You define:

"type" : "array",
"properties" : {
  "names" : {...},
  "volumes" : {
     "type" : array"
  },
  "properties" : { ...}
}

I understand you want an

array of objects where each objects contains: name and an array of objects

What I would expect to be phrased in JSON Schema as:

"type" : "array",
"items" : {        <============ here
  "type" : "object",
  "properties" : {
    "names" : {...},
    "volumes" : {
      "type" : array"
      "items" : {   <============ and here
        "type" : "object",
        "properties" : { ... }
      }
    },
  },
}

In JSON schema you need somehow define schema of contents of/items in an array (if you want to validate JSON array items against matching JSON schema). You can do it with "items" keyword and either using tuple syntax (if sequence of elements in array is important) or as an array of objects, where sequence is irrelevant but each object must conform to a specific schema. Yep, you can have even an array of different kinds of objects if you need to.

Please read: https://json-schema.org/understanding-json-schema/reference/array.html

and spec for https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.4

Hope it helped.

Answer from PsychoFish on Stack Overflow
🌐
JSON Schema
json-schema.org › learn › miscellaneous-examples
JSON Schema - Miscellaneous Examples
The schema below represents a complex object with various properties including name, age, address, and hobbies. The address property is an object with nested properties, and the hobbies property is an array of strings.
🌐
JSON Schema
json-schema.org › understanding-json-schema › reference › object
JSON Schema - object
See Additional Properties and Unevaluated Properties for how to disallow properties that don't match any of the property names in properties. For example, let's say we want to define a simple schema for an address made up of a number, street name and street type: ... { "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "enum": ["Street", "Avenue", "Boulevard"] } }}
🌐
JSON Schema
json-schema.org › understanding-json-schema › reference › array
JSON Schema - array
Just as unevaluatedProperties affects only properties in an object, unevaluatedItems affects only items in an array. Watch out! The word "unevaluated" does not mean "not evaluated by items, prefixItems, or contains." "Unevaluated" means "not successfully evaluated", or "does not evaluate to true". Like with ...
Top answer
1 of 4
28

I got it to work using this validator by nesting the part of the schema for the array elements inside a object with the name items. The schema now has two nested items fields, but that is because one is a keyword in JSONSchema and the other because your JSON actually has a field called items

JSONSchema:

{
   "type":"object",
   "properties":{
      "items":{
         "type":"array",
         "items":{
            "properties":{
               "item_id":{
                  "type":"number"
               },
               "quantity":{
                  "type":"number"
               },
               "price":{
                  "type":"number"
               },
               "title":{
                  "type":"string"
               },
               "description":{
                  "type":"string"
               }
            },
            "required":[
               "item_id",
               "quantity",
               "price",
               "title",
               "description"
            ],
            "additionalProperties":false
         }
      }
   }
}

JSON:

{
   "items":[
      {
         "item_id":1,
         "quantity":3,
         "price":30,
         "title":"item1 new name"
      },
      {
         "item_id":1,
         "quantity":16,
         "price":30,
         "title":"Test Two"
      }
   ]
}

Output with two errors about missing description fields:

[ {
  "level" : "error",
  "schema" : {
    "loadingURI" : "#",
    "pointer" : "/properties/items/items"
  },
  "instance" : {
    "pointer" : "/items/0"
  },
  "domain" : "validation",
  "keyword" : "required",
  "message" : "missing required property(ies)",
  "required" : [ "description", "item_id", "price", "quantity", "title" ],
  "missing" : [ "description" ]
}, {
  "level" : "error",
  "schema" : {
    "loadingURI" : "#",
    "pointer" : "/properties/items/items"
  },
  "instance" : {
    "pointer" : "/items/1"
  },
  "domain" : "validation",
  "keyword" : "required",
  "message" : "missing required property(ies)",
  "required" : [ "description", "item_id", "price", "quantity", "title" ],
  "missing" : [ "description" ]
} ]

Try pasting the above into here to see the same output generated.

2 of 4
10

I realize this is an old thread, but since this question is linked from jsonschema.net, I thought it might be worth chiming in...

The problem with your original example is that you're declaring "properties" for an "array" type, rather than declaring "items" for the array, and then declaring an "object" type (with "properties") that populates the array. Here's a revised version of the original schema snippet:

"items": {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "item_id": {"type" : "number"},
            "quantity": {"type": "number"},
            "price": {"type" : "decimal"},
            "title": {"type": "string"},
            "description": {"type": "string"}
        },
        "required": ["item_id","quantity","price","title","description"],
        "additionalProperties" : false
    }
}

I would recommend against using the term "items" for the name of the array, to avoid confusion, but there's nothing stopping you from doing that...

🌐
Google Groups
groups.google.com › g › json-schema › c › rgkxYocPSVg
JSON Schema: ordered properties
There is no way, in JSON, to say that for two objects o1 and o2, o1 is less than o2 if o1's "name" is lexically less than o2's "name". Relying on ordering of properties or whatever in any JSON value over the wire would require a preliminary agreement between the _producer_ of this JSON value and its consumer. As I do Java and use Jackson, I can testify that you _can_ bind Jackson so as to tell it to emit property members, or even array ...
🌐
Json-schema
tour.json-schema.org › content › 01-Getting-Started › 06-Array-of-Objects
Array of Objects: Getting Started | A Tour of JSON Schema
Learn how to define an array of objects with properties name and level, and how to set the items keyword in JSON schema.
🌐
Jsonschema2pojo
jsonschema2pojo.org
jsonschema2pojo
The 'optional' schema rule doesn't produce a structural change in generated Java types, it simply causes the text (Optional) to be added to the JavaDoc for fields, getters and setters. This schema rule is deprecated since Draft 03 of the JSON Schema specification. Rather than marking optional properties as optional, one should mark required properties as required. For properties of type 'array', setting uniqueItems to false (or omitting it entirely) causes the generated Java property to be of type java.util.List.
🌐
JSON Schema
json-schema.org › learn › getting-started-step-by-step
Creating your first schema
Inside the properties object, add the tags keyword. Include the usual schema annotations description and type, and define type as an array:
Find elsewhere
🌐
Cswr
cswr.github.io › JsonSchema › spec › arrays
Arrays - JSON Schema
In this case, we are asking that the first element must be a string, the second one an integer and the third one a boolean. For example, this array validates against the schema ... Note that the default behaviour of JSON Schema allows us to have fewer items, as long as the corresponding (sub)schemas are satisfied.
🌐
GitHub
github.com › java-json-tools › json-schema-validator › issues › 46
Using JSON schema with an array of mixed object types · Issue #46 · java-json-tools/json-schema-validator
March 6, 2013 - as far as I understand - this should be a valid schema: { "type" : "array", "items" : { "type" : [ { "type" : "object", "properties" : { "name" : { "type" : "string" }}}, { "type" : "object", "properties" : { "price" : { "type" : "number...
Author   ettig
🌐
GitHub
github.com › orgs › json-schema-org › discussions › 145
Contains not working as expected with array of objects · json-schema-org · Discussion #145
{ "$schema": "http://json-schema.org/draft-07/schema", "properties": { "elements": { "type": "array", "items": { "type": "object" }, "contains": { "properties": { "somePropertyA": { "type": "string", "enum": [ "true" ] } } } } }, "required":["elements"], }
🌐
Ajv
ajv.js.org › json-schema.html
JSON Schema | Ajv JSON schema validator
The value of the keyword is a map with keys equal to data object properties. Each value in the map should be either an array of unique property names ("property dependency" - see dependentRequired keyword) or a JSON Schema ("schema dependency" - see dependentSchemas keyword).
🌐
JSON Schema
json-schema.org › understanding-json-schema › structuring
JSON Schema - Modular JSON Schema combination
The URI https://example.com/schemas/address#/properties/street_address identifies the highlighted subschema in the following schema. ... { "$id": "https://example.com/schemas/address", "type": "object", "properties": { "street_address": { "type": "string" }, "city": { "type": "string" }, "state": { "type": "string" } }, "required": ["street_address", "city", "state"]}
Top answer
1 of 2
2

Does the second schema correctly identify that "arr is an array of objects that have an integer named type an integer, and either an object named Steps or an object named Heartrate"?

Yes, somewhat. You do not state which properties must exist, and which properties cannot exist together at the same time, which we can do with the "required" and "oneOf" keywords.

Here's an updated schema, and also fixing an error you made in the "Heartrate" section (you said "steps" instead of "heartrates"):

Copy{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "type": "object",
  "properties": {
    "arr": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [ "type" ],
        "oneOf": [
           { "required": ["Steps"] },
           { "required": ["HeartRate"] }
        },
        "properties": {
          "type": {
            "type": "integer"
          },
          "Steps": {
            "type": "object",
            "required": ["steps"],
            "properties": {
              "steps": {
                "type": "integer"
              }
            }
          },
          "HeartRate": {
            "type": "object",
            "required": ["heartrates"],
            "properties": {
              "heartrates": {
                "type": "integer"
              }
            }
          }
        }
      }
    }
  }
}

2 of 2
1

Well, it passes because technically it is valid, you can have any combination of objects in an array. This schema explicitly states that there can be a heartrate object. You say you're familiar with arrays of a single object type, but what you should know is an array doesn't care what types of objects are in it, which is why your introduced schema is in fact valid. Whether or not it fits the function you're trying to achieve is another question all together.

It would imply that you would need either one very complex loop to traverse the array when you need to pull an object, assuming there will be so many that you can't adequately index them, or you would need some sort of index with address to the objects in the array, which might be cumbersome to write but possible. So the question is, what are you intending to do with these objects? Seems obvious from the properties you're using, seems like a fitness monitor of some sort, but then what your intention to do with the data isn't apparent so it's difficult to say what you could do even if this schema is valid, which keep in mind that it is indeed a valid structure for an array.

Although if you do have two types of objects, one could ask why not simply have an array for each type which will have supporting data pulling functions specific to their contents. But again it asks what you're intending to do.

Hope this helps your thought process.

UPDATE...

Not knowing exactly what you are intending to do, here is what I suggest you use as your data-structure format.

Copylet someArray = [
  {
    Steps: {
      steps: 3500
    },
    HeartRate: {
      heartrates: 4000
    }
  },
  {
    Steps: {
      steps: 3500
    },
    HeartRate: {
      heartrates: 4000
    }
  }
]

You examples have some redundancy in them it seems, where they are explicitly stating that something is an object and something is a property of that object. JavaScript already knows all that so no need to add more complexity to the functions you create to work with these that will then have to dig through all those layers. I suggest that you create one object and each has a property of the type you've declared that is an object and that object can if you want be expanded or condensed as you desire. This will mitigate a lot of complexity to your structure. And so you'll see that you have an Array of Objects and those objects contain properties representing the data you're intending to gather.

But this assumes that the data you're gathering is from multiple sources. Again would need to know a bit more about what you're trying to accomplish.

Top answer
1 of 2
23

The schema you have written (assuming the commas are fixed) describes data of the form:

{
    "prop1": "Some string property goes here",
    "props": [
        {"key": "foo", "value": "bar"},
        {"key": "foo2", "value": "bar2"},
        ...
    ]
}

If this is what you wanted, then you are already finished.

However, I do wonder why you are using key/value pairs in an array, when you could use a JSON object with string keys instead. Using the additionalProperties keyword, you could have a schema:

{
    "type": "object",
    "name": "MyObj",
    "properties": {
        "prop1": {
            "type": "string",
            "description": "prop1"
        },
        "props": {
            "type": "object",
            "additionalProperties": {
                "type": "string",
                "description": "string values"
            }
        }
    }
}

This describes a data format like:

{
    "prop1": "Some string property goes here",
    "props": {
        "foo": "bar",
        "foo2": "bar2"
    }
}
2 of 2
0

At W3 schools (JSON Syntax) you can read how the array should be defined.

There is no schema like the xsd for xml, however i've found an approach on json-schema.org. If you are able to, i'll advice to youse google-GSON library for JSON. You could Store key Value as "id" : "value" and build only one object, containing all requieed pairs:

{ "lang" : "EN" , "color" : "red" }

Your posted model is incorect, you can check it on jsonlint.com Here is a working version, i'm not sure if the modell is as expected.

{
    "type": "object",
    "name": "MyObj",
    "properties": [
        {
            "prop1": {
                "type": "string",
                "description": "prop1",
                "required": true
            },
            "props": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "key": {
                            "type": "string",
                            "description": "key",
                            "required": true
                        },
                        "value": {
                            "type": "string",
                            "description": "the value",
                            "required": true
                        }
                    },
                    "description": "the value",
                    "required": true
                }
            }
        }
    ]
}
Top answer
1 of 5
73

I asked this same question on the JSON schema google group, and it was answered quickly. User fge asked that I post his response here:

Hello,

The current specification is draft v4, not draft v3. More specifically, the validation specification is here:

https://datatracker.ietf.org/doc/html/draft-fge-json-schema-validation-00

The web site is not up to date, I don't know why... I'll submit a pull request.

With draft v4 you can use this:

{
    "type": "array",
    "items": {
        "oneOf": [
            {"first": [ "schema", "here" ] }, 
            {"other": [ "schema": "here" ] }
        ]
    }  
}

For instance, this is a schema for an array where items can be either strings or integers (it can be written in a more simple way though):

{
    "type": "array",
    "items": {
        "oneOf": [
            {"type": "string"},
            {"type": "integer"}
        ]
    }
}

This is the correct answer. My corrected schema now includes:

"transactions" : {
    "type" : "array",
    "items" : {
        "oneOf" : [
            {
                "type" : "object",
                "properties" : {
                    "type" : {
                        "type" : "string",
                        "enum" : ["BUILD", "REASSIGN"]
                    }
                }
            },
            {
               "type" : "object",
               "properties" : {
                 "type" : {
                   "type" : "string",
                   "enum" : ["BREAK"]
                  }
               }
            }
        ]
    }
}
2 of 5
7

I've been looking into this for quite a while too. But haven't been able to find a working solution. It works fine if you have only one schema eg.

"transactions" : {
          "type" : "array",
          "items" : 
          {
            "type" : "object",
            "properties" : {
              "type" : {
                "type" : "string",
                "enum" : ["BREAK"]
              },
          }
}

Then you just skip the array brackets, and use an object. However if you want to do what you are doing, there seems to be no solid answer. This is the only thing that I've found so far: http://the-long-dark-tech-time.blogspot.se/2012/12/using-json-schema-with-array-of-mixed.html

🌐
APIMatic
apimatic.io › openapi › array-of-objects
OpenAPI Array of Objects
The array is inline, but the items are defined as a referenced schema component. See the reasons for Reference Array of Objects as they are similar. Generating code from an OpenAPI specification with an inline array of objects using object references, the resulting code typically represents the array as a native collection type in the target programming language. For example, generated Java code would use List<User> to represent the array of User objects.