1

我已将我的 JSON 模式拆分为多个文件,并根据需要以标准方式 ( "$ref": http://rootpath/otherfile.json#/definitions/link) 引用它们。

JSON 文件是项目中的嵌入资源。这些rootpath变化取决于它的部署位置。但是在生产中一切正常(发出请求,获得 JSON 响应作为模式,当针对模式 NJsonSchema 验证响应时,内部获取参考模式并提取完成验证所需的内容)

但是,当涉及到测试时,情况就不同了。响应很好,并且第一个模式被删除了。这rootpath是这样的,一切都是相对的,http://testapi/但实际上并不存在。因此,当 NJsonSchema 尝试获取参考架构时,它会查找类似 的http://testapi/otherfile.json#/definitions/link内容,这显然失败了。

通过阅读本文,我想我想使用重载来获取JsonSchema4允许我指定 JsonReferenceResolver 的对象,然后我可以在生产中使用默认值并注入我自己的进行测试,以便它在$ref我的某个地方查找 s控制并且将存在。但我看不到任何关于此的文档或示例。

示例模式:

{ // root.json
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "@Model.Root/schemas/root.json",
    "title": "Root",
    "properties": {
        "link": { "$ref": "@Model.Root/schemas/common.json#/definitions/link" }             
    },
    "required": [ "link" ]
}

{ // common.json - different file to the above
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "@Model.Root/schemas/common.json",
    "definitions": {
        "link": {
            "title": "Link",
            "type": "object",
            "properties": {
                "rel": { "type": "string" },
                "href": { "type": "string" }
            },
            "required": [ "rel", "href" ]
        }
    }
}

示例响应:

{
    "schema": "http://testapi/schemas/root.json",
    "link": { "rel": "self", "href": "http://testapi/root" }
};

验证码(C#):

using NJsonSchema;
using NJsonSchema.Validation;
...
JsonSchema4 schema = await JsonSchema4.FromJsonAsync(<contents of root.json file>);
string response = "{ ""link"": { ""rel"": ""self"", ""href"": ""http://testapi/root"" } }";
ICollection<ValidationError> errors = schema.Validate(response);
...
4

1 回答 1

3

我指定 JsonReferenceResolver 的预感是正确的。在上面的示例中,我无法在测试环境中从 root.json 中获取对 common.json 的引用以“工作”,因为在该环境中服务/路径不存在。

因此,在设置环境时,我确实知道 common.json 是什么,即我知道它的内容为字符串,因此可以将其作为模式 ( JsonSchema4 commonSchema = JsonSchema4.FromJsonAsync(commonJsonAsString).Result;) 获取。

使用它,我可以设置一个“参考解析器工厂”并在其中添加一个文档参考,以便所有参考http://testapi/schemas/common.json#/...都来自我的commonSchemaie

private Func<JsonSchema4, JsonReferenceResolver> referenceResolverFactory;
this.referenceResolverFactory = x =>
{
    JsonSchemaResolver schemaResolver = new JsonSchemaResolver(x, new JsonSchemaGeneratorSettings());
    JsonReferenceResolver referenceResolver = new JsonReferenceResolver(schemaResolver);
    referenceResolver.AddDocumentReference("http://testapi/schemas/common.json", commonSchema);

    return referenceResolver;
};

可以通过以相同方式添加更多文档引用来解决不同的引用。

然后,当我尝试转换 root.json 模式(引用 common.json)或另一个模式(引用 common.json)时,我使用了一个重载,FromJsonAsync其中传入referenceResolverFactory

private bool GetAndValidateResponse(string schemaName, string response, string schemaAsString)
{
    // schemaName:     Name of the schema being validated, e.g. "root.json"
    // response:       http response body as a string, see 'Example response' in question
    // schemaAsString: The schema being validate as a string, e.g. root.json contents in question
    //
    // Check the response object against the schema
    JsonSchema4 schema = JsonSchema4.FromJsonAsync(schemaAsString, schemaName, this.referenceResolverFactory).Result;
    ICollection<ValidationError> errors = schema.Validate(response);

    return errors.Count < 1;
}

在我的单元测试案例中,我只对它是否有效感兴趣,因此是布尔返回值。如果您显然对确切的错误感兴趣,您可以返回该集合。

此外,每个单元测试类我只设置一次工厂,而不是每个测试。但是,它正确地进入了每个ref模式中的每个工厂。

于 2018-06-13T07:56:45.303 回答