JSchemaGenerator 多维数组

JSchemaGenerator multidimensional array

我有一个 class MyClass 包含 属性 int[,] MyProperty.

使用 new JSchemaGenerator().Generate(typeof(MyClass)) 生成 json 架构时,架构包含

"MyProperty": {
  "type": "array",
  "items": {
    "type": "integer"
  }
}

而我希望架构包含一个数组数组(即多维数组),如下所示

"MyProperty": {
  "type": "array",
  "items": {
    "type": [
      "array",
      "null"
    ],
    "items": {
      "type": "integer"
    }
  }
}

请注意,JSchemaGenerator 确实会为锯齿状数组生成所需的输出 T[][]

我不相信 JSON Schema standard supports a "rectangular array" constraint, see How to define a two-dimensional rectangular array in JSON Schema? 进行确认。 Json.NET 模式为二维数组生成一维数组模式这一事实似乎是一个纯粹的错误。

作为解决方法,使用 custom JSchemaGenerationProvider,您可以为 N 维多维数组生成 N 维锯齿状数组架构。这样的模式不会捕获行都具有相同长度的约束,但它至少会捕获正确的数组嵌套深度。

首先定义如下JSchemaGenerationProvider:

public class MultidimensionalArraySchemaProvider : JSchemaGenerationProvider
{
    public override JSchema GetSchema(JSchemaTypeGenerationContext context)
    {
        if (CanGenerateSchema(context))
        {
            // Create a jagged N-d array type.
            var type = context.ObjectType.GetElementType().MakeArrayType();
            for (int i = context.ObjectType.GetArrayRank(); i > 1; i--)
                // Disallow null array items for outer arrays
                // context.Generator.DefaultRequired controls whether null is allowed for innermost array items.
                type = typeof(ArrayRow<>).MakeGenericType(type);
            // Return a schema for the jagged N-d array type.
            return context.Generator.Generate(type);
        }
        else
            throw new NotImplementedException();
    }
    
    public override bool CanGenerateSchema(JSchemaTypeGenerationContext context) => 
        context.ObjectType.IsArray && context.ObjectType.GetArrayRank() > 1;
}

[JsonArray(AllowNullItems = false)]
class ArrayRow<T> : List<T> { }

那么,如果您的 class 看起来像:

public class MyClass 
{
    public int[,] MyProperty { get; set; }

    public string[,,,] MyProperty4D { get; set; }
}

你可以这样做:

var generator = new JSchemaGenerator();
generator.GenerationProviders.Add(new MultidimensionalArraySchemaProvider());
var schema = generator.Generate(typeof(MyClass));           

结果:

{
  "type": "object",
  "properties": {
    "MyProperty": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {
          "type": "integer"
        }
      }
    },
    "MyProperty4D": {
      "type": "array",
      "items": {
        "type": "array",
        "items": {
          "type": "array",
          "items": {
            "type": "array",
            "items": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        }
      }
    }
  },
  "required": [
    "MyProperty",
    "MyProperty4D"
  ]
}

演示 fiddle here.

相关问题:

  • How to make a two dimensional array in JSON Schema? - 答案展示了如何为具有 预定义的二维数组创建 JSON 模式, 固定尺寸。您的问题并未表明您的 MyProperty 数组具有已知的行长度,但如果已知,则此问题说明了如何创建适当的模式。

  • - 回答:目前不可能。

  • JSON Schema Compare two properties to be equal length array - answer by Jason Desrosiers在 JSON 架构中,所有验证关键字的范围都在它适用的值范围内。换句话说,您不能根据另一个值来验证一个值。