array¶
Arrays are used for ordered elements. In JSON, each element in an array may be of a different type.
list
or tuple
type,
depending on usage. However, the json
module in the Python
standard library will always use Python lists to represent JSON
arrays.Array
type.{ "type": "array" }
[1, 2, 3, 4, 5]
[3, "different", { "types" : "of values" }]
{"Not": "an array"}
Items¶
There are two ways in which arrays are generally used in JSON:
- List validation: a sequence of arbitrary length where each item matches the same schema.
- Tuple validation: a sequence of fixed length where each item may
have a different schema. In this usage, the index (or location) of
each item is meaningful as to how the value is interpreted. (This
usage is often given a whole separate type in some programming
languages, such as Python’s
tuple
).
List validation¶
List validation is useful for arrays of arbitrary length where each
item matches the same schema. For this kind of array, set the
items
keyword to a single schema that will be used to validate all
of the items in the array.
Note
When items
is a single schema, the additionalItems
keyword
is meaningless, and it should not be used.
In the following example, we define that each item in an array is a number:
{
"type": "array",
"items": {
"type": "number"
}
}
[1, 2, 3, 4, 5]
A single “non-number” causes the whole array to be invalid:
[1, 2, "3", 4, 5]
The empty array is always valid:
[]
Tuple validation¶
Tuple validation is useful when the array is a collection of items where each has a different schema and the ordinal index of each item is meaningful.
For example, you may represent a street address such as:
1600 Pennsylvania Avenue NW
as a 4-tuple of the form:
[number, street_name, street_type, direction]
Each of these fields will have a different schema:
number
: The address number. Must be a number.street_name
: The name of the street. Must be a string.street_type
: The type of street. Should be a string from a fixed set of values.direction
: The city quadrant of the address. Should be a string from a different set of values.
To do this, we set the items
keyword to an array, where each item
is a schema that corresponds to each index of the document’s array.
That is, an array where the first element validates the first element
of the input array, the second element validates the second element of
the input array, etc.
Here’s the example schema:
{
"type": "array",
"items": [
{ "type": "number" },
{ "type": "string" },
{ "enum": ["Street", "Avenue", "Boulevard"] },
{ "enum": ["NW", "NE", "SW", "SE"] }
]
}
[1600, "Pennsylvania", "Avenue", "NW"]
“Drive” is not one of the acceptable street types:
[24, "Sussex", "Drive"]
This address is missing a street number
["Palais de l'Élysée"]
It’s okay to not provide all of the items:
[10, "Downing", "Street"]
And, by default, it’s also okay to add additional items to end:
[1600, "Pennsylvania", "Avenue", "NW", "Washington"]
Addtional Items¶
The additionalItems
keyword controls whether it’s valid to have
additional items in a tuple beyond what is defined in items
. The
value of the additionalItems
keyword is a schema that all
additional items must pass in order for the keyword to validate. This
keyword is ignored if there is not a “tuple validation” items
keyword present in the same schema.
additionalItems
does not require a "tuple
validation" items
keyword to be present. There are no
constraints on any of the items, so all items are considered to be
additional items.Here, we’ll reuse the example schema above, but set
additionalItems
to false
, which has the effect of disallowing
extra items in the array.
{
"type": "array",
"items": [
{ "type": "number" },
{ "type": "string" },
{ "enum": ["Street", "Avenue", "Boulevard"] },
{ "enum": ["NW", "NE", "SW", "SE"] }
],
"additionalItems": false
}
[1600, "Pennsylvania", "Avenue", "NW"]
It’s ok to not provide all of the items:
[1600, "Pennsylvania", "Avenue"]
But, since additionalItems
is false
, we can’t provide
extra items:
[1600, "Pennsylvania", "Avenue", "NW", "Washington"]
You can express more complex constraints by using a non-boolean schema to constrain what value additional items can have. In that case, we could say that additional items are allowed, as long as they are all strings:
{
"type": "array",
"items": [
{ "type": "number" },
{ "type": "string" },
{ "enum": ["Street", "Avenue", "Boulevard"] },
{ "enum": ["NW", "NE", "SW", "SE"] }
],
"additionalItems": { "type": "string" }
}
Extra string items are ok …
[1600, "Pennsylvania", "Avenue", "NW", "Washington"]
… but not anything else
[1600, "Pennsylvania", "Avenue", "NW", 20500]
Note
Because “list validation” (items
is an object) applies to all
items in the list three are no additional items and therefore
additionalItems
has nothing to apply its schema to and will
have no effect.
Contains¶
New in draft 6
While the items
schema must be valid for every item in the array, the
contains
schema only needs to validate against one or more items in the
array.
{
"type": "array",
"contains": {
"type": "number"
}
}
A single “number” is enough to make this pass:
["life", "universe", "everything", 42]
But if we have no number, it fails:
["life", "universe", "everything", "forty-two"]
All numbers is, of course, also okay:
[1, 2, 3, 4, 5]
Length¶
The length of the array can be specified using the minItems
and
maxItems
keywords. The value of each keyword must be a
non-negative number. These keywords work whether doing
List validation or Tuple validation.
{
"type": "array",
"minItems": 2,
"maxItems": 3
}
[]
[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
Uniqueness¶
A schema can ensure that each of the items in an array is unique.
Simply set the uniqueItems
keyword to true
.
{
"type": "array",
"uniqueItems": true
}
[1, 2, 3, 4, 5]
[1, 2, 3, 3, 4]
The empty array always passes:
[]