Json Schema Patterns in .NET - Creating an array of higher rank
In this series we are cataloging common patterns with JSON Schema and the .NET code generated by Corvus.JsonSchema.
It is especially useful for developers who want to move to a schema-first approach, but are unsure how that will map to their .NET code.
We are focusing on draft 2020-12 and the dotnet8.0 code generation, but very similar patterns apply for older versions of both .NET and draft 2019-09, draft 7, and even draft 6. We will highlight the key differences as we go.
If you have no experience of JSON Schema at all, I would recommend you read the getting started step-by-step documentation provided by the JSON Schema team.
Defining the type and rank of an array
You can think of an array of rank > 1 as being like an "array of arrays".
The rank of an array determines the number of indices you need to provide to access a value.
In C#, for example, we might define an array of rank 2 like this
double[][] values = new double[3][4];
To retreive a value we need to provide 2 indices
double value = values[1][0];
We have seen how JSON schema allows you to define an array that contains items of a particular type using its items
property.
This was an array of rank 1. Only one index was required to retrieve the value.
To create an array of higher rank, just like the C# example above, we define each item to itself be an array.
Each array we define can be constrained with minItems
and/or maxItems
to ensure the dimensions are appropriate.
Specifying both, and making them the same value implies an array of exactly that number of items.
Ragged multi-dimensional arrays (where each item may be an array of a different length) can be created by not specifying the upper and lower limits on one of the arrays, allowing them to be any length.
Remember:
- Specifying both
maxItems
andminItems
, and making them the same value constraints the array to exactly the given length. - Specifying just
maxItems
indicates that the array can contain up to that many items. - Specifying just
minItems
indicates that the array will contain at least that many items. - Specifying both, and making them different values gives an upper and a lower bound to the number of items.
File: matrix-2d.json
{
"title": "A 4x2 array of JsonDouble",
"type": "array",
"items": { "$ref": "#/$defs/row" },
"minItems": 4,
"maxItems": 4,
"$defs": {
"row": {
"type": "array",
"minItems": 2,
"maxItems": 2,
"items": { "type": "number", "format": "double" }
}
}
}
Generate the code:
generatejsonschematypes --outputPath Model --rootNamespace JsonSchemaSample.Api matrix-2d.json
Generating: Row
Generating: Matrix2d
using JsonSchemaSample.Api;
// Initialize a 2D array using collection initialization expressions
Matrix2d matrix =
[
[1.3, 1.4],
[2.4, 3.2],
[9.4, 6.2],
[4.4, 9.4]
];
// Access an element of a 2D array.
double value = matrix[2][1];
// Set the item at the given indices in the 2D array
Matrix2d updatedMatrix = matrix.SetItem(2, 1, 3.4);
double updateMatrixValue = updatedMatrix[2][1];
Console.WriteLine(updatedMatrix);