Skip to content
Matthew Adams By Matthew Adams Co-Founder
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 and minItems, 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

Example code

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);

Matthew Adams

Co-Founder

Matthew Adams

Matthew was CTO of a venture-backed technology start-up in the UK & US for 10 years, and is now the co-founder of endjin, which provides technology strategy, experience and development services to its customers who are seeking to take advantage of Microsoft Azure and the Cloud.