使用 AJV 验证针对 JSON 模式的 API 响应

Validate an API response against JSON schema using AJV

我花了很多天时间阅读了大量内容并对此进行了多次测试,但没有得到预期的结果。 我需要使用 JSON 架构 (Swagger 2.0) 验证 API 响应。 JSON 更长,但我已将其简化为简单。我需要知道响应中的 "code" 和 "message" 关键字是否定义了类型和值。这是我使用的代码:

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

var schema = {
  "host": "cert",
  "paths": {
    "products": {
      "get": {
        "responses": {
          "401": {
            "description": "Problem with the client request",
            "headers": {
              "x-correlator": {
                "type": "string",
                "format": "uuid",
                "description": "Correlation id"
              }
            },
            "schema": {
              "$ref": "file:///../errors.json#/definitions/Unauthenticated"
            }
          }
        }
      }
    },
    "products": {
      "get": {
        "responses": {
          "401": {
            "description": "Problem with the client request",
            "headers": {
              "x-correlator": {
                "type": "string",
                "format": "uuid",
                "description": "Correlation id"
              }
            },
            "schema": {
              "$ref": "file:///../errors.json#/definitions/Unauthenticated"
            },
            "examples": {
              "application/json": {
                "code": "UNAUTHENTICATED",
                "message": "Authentication error"
              }
            }
          }
        }
      }
    }
  }
}

var errors_schema = {
  "info": {
    "description": "Common errors",
    "version": "3.0.1",
    "title": "Common errors",
    "contact": {
      "name": "Team"
    }
  },
  "definitions": {
    "ModelError": {
      "type": "object",
      "required": [
        "message"
      ],
      "properties": {
        "message": {
          "type": "string",
          "description": "A human readable description"
        }
      }
    },
    "Unauthenticated": {
      "allOf": [
        {
          "type": "object",
          "required": [
            "code"
          ],
          "properties": {
            "code": {
              "type": "string",
              "enum": [
                "UNAUTHENTICATED"
              ],
              "default": "UNAUTHENTICATED",
              "description": "Request not authenticated due to missing, invalid, or expired credentials."
            }
          }
        },
        {
          "$ref": "#/definitions/ModelError"
        }
      ]
    }
  }
}

ajv.addSchema(errors_schema, 'file:///../errors.json');
var testajv = ajv.compile(schema);

var response = {"code": 123, "message":"token expired"}

var valid = testajv(response);

console.log(valid);

if(!valid) {
    console.log(testajv.errors);
}

如您所见,响应中的关键字 "code" 是“123”整数,但在模式中它被定义为字符串。独立于验证总是获得 'true' 的值。我应该怎么做才能满足我的需求?提前致谢。

在代码中使用类型作为数字而不是字符串 属性。

"properties": {
        "code": {
          "type": "number",
          "enum": [
            "UNAUTHENTICATED"
          ],
          "default": "UNAUTHENTICATED",
          "description": "Request not authenticated due to missing, invalid, or expired credentials."
        }
      }

Swagger 架构包含多个 JSON 架构,组织为 API 结构,您需要解决 Swagger 架构的正确部分以使用 JSON 架构进行验证。

请检查示例代码 (https://runkit.com/embed/bwj42juwyjo4):

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

var schema = {
  "host": "cert",
  "paths": {
    "products": {
      "get": {
        "responses": {
          "401": {
            "description": "Problem with the client request",
            "headers": {
              "x-correlator": {
                "type": "string",
                "format": "uuid",
                "description": "Correlation id"
              }
            },
            "schema": {
              "$ref": "errors.json#/definitions/Unauthenticated"
            }
          }
        }
      }
    },
    "products": {
      "get": {
        "responses": {
          "401": {
            "description": "Problem with the client request",
            "headers": {
              "x-correlator": {
                "type": "string",
                "format": "uuid",
                "description": "Correlation id"
              }
            },
            "schema": {
              "$ref": "errors.json#/definitions/Unauthenticated"
            },
            "examples": {
              "application/json": {
                "code": "UNAUTHENTICATED",
                "message": "Authentication error"
              }
            }
          }
        }
      }
    }
  }
}

var errors_schema = {
  "info": {
    "description": "Common errors",
    "version": "3.0.1",
    "title": "Common errors",
    "contact": {
      "name": "Team"
    }
  },
  "definitions": {
    "ModelError": {
      "type": "object",
      "required": [
        "message"
      ],
      "properties": {
        "message": {
          "type": "string",
          "description": "A human readable description"
        }
      }
    },
    "Unauthenticated": {
      "allOf": [
        {
          "type": "object",
          "required": [
            "code"
          ],
          "properties": {
            "code": {
              "type": "string",
              "enum": [
                "UNAUTHENTICATED"
              ],
              "default": "UNAUTHENTICATED",
              "description": "Request not authenticated due to missing, invalid, or expired credentials."
            }
          }
        },
        {
          "$ref": "#/definitions/ModelError"
        }
      ]
    }
  }
}

ajv.addSchema(errors_schema, 'errors.json');
ajv.addSchema(schema, 'swagger.json')



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

console.log(testajv({"code": 123, "message":"token expired"}), testajv.errors); // Fails

console.log(testajv({"code": "AAA", "message":"token expired"}), testajv.errors); // Fails

console.log(testajv({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv.errors); // Passes

var testajv2 = ajv.compile({ $ref: 'swagger.json#/paths/products/get/responses/401/schema' });

console.log(testajv2({"code": 123, "message":"token expired"}), testajv2.errors); // Fails

console.log(testajv2({"code": "AAA", "message":"token expired"}), testajv2.errors); // Fails

console.log(testajv2({"code": "UNAUTHENTICATED", "message":"token expired"}), testajv2.errors); // Passes

有关 ajv 问题的更多信息:https://github.com/epoberezkin/ajv/issues/195