使用 AJV 针对 JSON 架构的 API 验证响应期间输出错误

Wrong output during API validation response against JSON schema using AJV

我正在使用 AJV 验证针对 JSON 模式的 API 响应(招摇)。这是进行验证的脚本:

var Ajv = require('ajv');
var ajv = new Ajv();

var schema = {
    "paths": {
      "/users": {
        "get": {
          "security": [
            {
              "3_legged": [
                "userprofile-search"
              ]
            }
          ],
          "parameters": [
            {
              "$ref": "#/parameters/IdentitiesId"
            },
            {
              "$ref": "#/parameters/IdDocumentValue"
            },
            {
              "$ref": "#/parameters/IdDocumentType"
            }
          ],          
          "responses": {
            "200": {
              "headers": {
                "x-correlator": {
                  "type": "string",
                  "format": "uuid",
                }
              },
              "schema": {
                "type": "array",
                "items": {
                  "$ref": "#/definitions/UserProfile"
                }
              }
            }
          }
        }
      },
      "/users/{user_id}": {
        "get": {
          "security": [
            {
              "3_legged": [
                "userprofile-read"
              ]
            }
          ],
          "tags": [
            "users"
          ],
          "operationId": "getUserProfileInfo",
          "parameters": [
            {
              "$ref": "#/parameters/UserId"
            }
          ],          
          "responses": {
            "200": {
              "description": "OK",
              "headers": {
                "x-correlator": {
                  "type": "string",
                  "format": "uuid",
                  "description": "Correlation id"
                }
              },
              "schema": {
                "$ref": "#/definitions/UserProfile"
              },
              "examples": {
                "application/json": {
                  "id": "A000-0000-0001",
                  "name": "Andrés Iniesta",
                  "id_document": {
                    "country": "ES",
                    "type": "NIF",
                    "value": "value"
                  },
                  "identities": [
                    {
                      "type": "email",
                      "id": "id",
                      "services": [
                        "iptv",
                        "email"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "mobile"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "mobile"
                      ]
                    },
                    {
                      "type": "phone_number",
                      "id": "id",
                      "services": [
                        "landline",
                        "broadband"
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
  "definitions": {
    "UserProfile": {
      "type": "object",
      "required": [
        "id",
        "name",
        "identities"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "id_document": {
          "$ref": "common.json#/definitions/IdDocument"
        },
        "identities": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Identity"
          }
        }
      }
    },
    "Identity": {
      "type": "object",
      "required": [
        "id",
        "services",
        "type"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "phone_number",
            "email",
            "uid"
          ]
        },
        "services": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": [
              "mobile",
              "invoicing"
            ]
          }
        },
        "id": {
          "type": "string"
        }
      }
    }
  }
}

var common = {
  "definitions": {
    "MoneyAmount": {
      "type": "object",
      "properties": {
        "amount": {
          "type": "number"
        }
      }
    },
    "IdDocument": {
      "type": "object",
      "required": [
        "country",
        "type",
        "value"
      ],
      "properties": {
        "country": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "value": {
          "type": "string"
        }
      }
    }
  }
}

var response={
    "id": "123456789",
    "name": "pruebas trocafone prepago",
    "id_document": {
        "country": "ARG",
        "type": "P",
        "value": "15042016"
    },
    "identities": [
        {
            "type": "uid",
            "services": [
                "invoicing"
            ],
            "id": "511644813"
        },
        {
            "type": "phone_number",
            "services": [
                "mobile"
            ],
            "id": "00123456789"
        },
        {
            "type": "email",
            "services": [
                "email"
            ],
            "id": ""
        }
    ]
}

ajv.addSchema(schema, 'user_profile.json');
ajv.addSchema(common, 'common.json');

var testajv = ajv.compile({ $ref: 'common.json#/definitions/IdDocument' });

console.log(testajv(JSON.stringify(response)), testajv.errors);

然后,我得到这个输出:

schema id ignored A000-0000-0001
false [ { keyword: 'type',
    dataPath: '',
    schemaPath: 'common.json#/definitions/IdDocument/type',
    params: { type: 'object' },
    message: 'should be object' } ]

1- 我不明白为什么 ajv 告诉我 "schema id" 被忽略了。为什么它很重要?

2- 为什么它告诉我 IdDocument/type "should be object"?它是响应中的对象,定义如下:

"id_document": {
    "country": "ARG",
    "type": "P",
    "value": "15042016"
}

有人能帮我理解一下吗?提前致谢!

Swagger Schema 不是 JSON Schema,因此您必须在 Swagger Schema (schema.definitions.UserProfile) 中找到正确的位置。

虽然 Swagger Definition 并非 100% 兼容 JSON Schema,但在大多数情况下您可以使用通用验证器。

更多信息:https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject

您需要删除 JSON.stringify,因为它会从您的数据中创建 stringstring 不是 object)。

ajv.addSchema(schema.definitions.UserProfile, 'user_profile.json');
ajv.addSchema(common, 'common.json');

var testajv = ajv.compile({ $ref: 'common.json#/definitions/IdDocument' });

console.log(testajv(response), ajv.errorsText(testajv.errors));

https://runkit.com/embed/kn4gp1fs8vat