无法获取 JSON.NET 架构来查找我的外部引用 JSON 架构文件

Can't get JSON.NET Schema to find my externally referenced JSON schema files

我正在尝试验证我针对第三方提供的 JSON 模式创建的一些 REST Web API 函数的输出。我正在使用 .NET 4.8 控制台应用程序进行验证。

我正在使用 JSON.NET 架构 (v3.0.0),并且一直在努力解决这个问题:我的 project-response.json 架构文件看起来像这样:

{
  "$id": "http://www.whereever.com/services/projects/project-response.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "project response definition",
  "type": "object",
  "properties": {
    ....
    "lead": {
      "description": "The lead person",
      "$ref": "common-types.json#/definitions/personType"
    },
    ....
  }
}

除其他外,它还包含对同一目录中 common-types.json 文件的引用,该文件定义了架构各个部分使用的一些基本类型 - 如下所示:

{
  "$id": "http://www.whereever.com/services/projects/common-types.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "description": "common type definitions",
  "definitions": {
     ....
    "personType": {
      "type": "object",
      "properties": {
        "firstname": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "lastname": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "email": {
          "type": "string",
          "minLength": 1,
          "maxLength": 256
        }
      },
      "required": [
        "firstname",
        "lastname"
      ]
    }, 
    

我收到一个 JSON 字符串作为 API 调用的响应,我想根据此模式验证此 JSON。我试过这样做:

public bool Validate(string jsonData)
{
    string jsonSchemaFileName = Path.Combine(_schemaBaseDirectory, "project-response.json");
    
    // define a Json Text Reader for the schema
    using (StreamReader schemaFile = File.OpenText(jsonSchemaFileName))
    using (JsonTextReader reader = new JsonTextReader(schemaFile))
    {
        JSchemaUrlResolver resolver = new JSchemaUrlResolver();

        JSchemaReaderSettings settings = new JSchemaReaderSettings
                                                 {
                                                     Resolver = resolver,
                                                     BaseUri = new Uri(jsonSchemaFileName)
                                                 };

        JSchema schema = JSchema.Load(jsonReader, settings);

        // validate
        JToken jsonToken = JObject.Parse(jsonData);

        bool isValid = jsonToken.IsValid(schema, out IList<string> errors);

        return isValid;
    }
}

我原以为 JSON.NET 架构系统现在能够从 project-response.json 所在的相同位置读取 common-types.json 并在该公共目录中查找定义文件 - 但是,在线

JSchema schema = JSchema.Load(jsonReader, settings);

我一直收到错误消息:

Newtonsoft.Json.Schema.JSchemaReaderException
HResult=0x80131500
Message=Error when resolving schema reference 'common-types.json#/definitions/projectIdType'. Path 'properties.id', line 7, position 11.

Source=Newtonsoft.Json.Schema

StackTrace:
at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ResolveDeferedSchema(DeferedSchema deferedSchema) at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ResolveDeferedSchemas() at Newtonsoft.Json.Schema.Infrastructure.JSchemaReader.ReadRoot(JsonReader reader, Boolean resolveDeferedSchemas) at Newtonsoft.Json.Schema.JSchema.Load(JsonReader reader, JSchemaReaderSettings settings)

Inner Exception 1:
WebException: The remote server returned an error: (404) Not Found.

知道为什么会失败吗?我错过了一些重要的事情吗?

您需要从 project-response.json 中删除 $id,因为它将定义 $ref 的基础 url。看到这个 link。 或者使用 JSchemaPreloadedResolver 预加载 common-types.json like

JSchemaPreloadedResolver resolver = new JSchemaPreloadedResolver();
using(var commontypes = File.Open(jsonSchemaCommonTypeFileName, FileMode.Open))
{
    resolver.Add(new Uri("http://www.whereever.com/services/projects/common-types.json"), commontypes);
}