【问题标题】:JSchemaGenerator multidimensional arrayJSchemaGenerator 多维数组
【发布时间】:2021-04-23 15:38:24
【问题描述】:

我有一个类 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[][] 生成所需的输出。

  • 为什么交错数组和多维数组的架构生成不同?
  • 是否可以在多维数组属性的顶部放置一个属性来更正架构生成?

【问题讨论】:

  • 这听起来像是向您正在使用的库的维护者提出的问题。
  • 如果您生成的架构符合您的预期和上面列出的内容,该怎么办?
  • 我不相信jsonschema 支持二维矩形阵列,请参阅How to define a two-dimensional rectangular array in JSON Schema?。但是,您可以为二维多维数组自动生成锯齿状二维数组的模式,请参阅dotnetfiddle.net/pcjxfG。这能满足您的需求吗?
  • @Zonus 这实际上就是我生成上述 sn-ps 的方式

标签: c# json.net jsonschema


【解决方案1】:

我不相信JSON Schema 标准支持“矩形阵列”约束,请参阅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> { }

那么,如果你的班级看起来像:

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"
  ]
}

演示小提琴here.

相关问题:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2011-10-03
    相关资源
    最近更新 更多