缺失引用错误:无法从该ID解析引用

前端开发 2026-07-09

我在尝试使用Ajv库来验证我的数据。我在JSON Schema中指定了多种类型:SetUserAccountDataPayloadUpdateUserAccountDataPayloadRemoveUserAccountDataPayload,以此类推。

我想实现的是能够像下面这样访问这些类型定义:

schema.definitions.SetUserAccountDataPayload

不过,我遇到了一个错误:

Uncaught MissingRefError: can't resolve reference #/definitions/UserAccountData from id #

import Ajv from 'ajv';
import schema from 'app/features/cross-platform-bridge/types/cross-platform-bridge.types.json';

const ajv = new Ajv();

const validate1 = ajv.compile<SetUserAccountDataPayload>(schema.definitions.SetUserAccountDataPayload);
const validate2 = ajv.compile<UpdateUserAccountDataPayload>(schema.definitions.UpdateUserAccountDataPayload);
const validate3 = ajv.compile<RemoveUserAccountDataPayload>(schema.definitions.RemoveUserAccountDataPayload);

架构:

{
  "$ref": "#/definitions/SchemaRoot",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "AtLeastOne<UserAccountData>": {
      "anyOf": [
        {
          "additionalProperties": false,
          "properties": {
            "firstTimeDeposited": {
              "type": "boolean"
            },
            "kycState": {
              "$ref": "#/definitions/VerificationStatus"
            },
            "lastDepositedAt": {
              "type": "string"
            },
            "sessionStatus": {
              "$ref": "#/definitions/SessionStatus"
            },
            "userId": {
              "type": "string"
            }
          },
          "required": [
            "userId"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "firstTimeDeposited": {
              "type": "boolean"
            },
            "kycState": {
              "$ref": "#/definitions/VerificationStatus"
            },
            "lastDepositedAt": {
              "type": "string"
            },
            "sessionStatus": {
              "$ref": "#/definitions/SessionStatus"
            },
            "userId": {
              "type": "string"
            }
          },
          "required": [
            "sessionStatus"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "firstTimeDeposited": {
              "type": "boolean"
            },
            "kycState": {
              "$ref": "#/definitions/VerificationStatus"
            },
            "lastDepositedAt": {
              "type": "string"
            },
            "sessionStatus": {
              "$ref": "#/definitions/SessionStatus"
            },
            "userId": {
              "type": "string"
            }
          },
          "required": [
            "kycState"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "firstTimeDeposited": {
              "type": "boolean"
            },
            "kycState": {
              "$ref": "#/definitions/VerificationStatus"
            },
            "lastDepositedAt": {
              "type": "string"
            },
            "sessionStatus": {
              "$ref": "#/definitions/SessionStatus"
            },
            "userId": {
              "type": "string"
            }
          },
          "required": [
            "firstTimeDeposited"
          ],
          "type": "object"
        },
        {
          "additionalProperties": false,
          "properties": {
            "firstTimeDeposited": {
              "type": "boolean"
            },
            "kycState": {
              "$ref": "#/definitions/VerificationStatus"
            },
            "lastDepositedAt": {
              "type": "string"
            },
            "sessionStatus": {
              "$ref": "#/definitions/SessionStatus"
            },
            "userId": {
              "type": "string"
            }
          },
          "required": [
            "lastDepositedAt"
          ],
          "type": "object"
        }
      ]
    },
    "RemoveUserAccountDataPayload": {
      "additionalProperties": false,
      "properties": {
        "data": {
          "type": "null"
        },
        "type": {
          "type": "string"
        },
        "version": {
          "type": "string"
        }
      },
      "required": [
        "data",
        "type",
        "version"
      ],
      "type": "object"
    },
    "SchemaRoot": {
      "additionalProperties": false,
      "properties": {
        "removeUserAccountDataPayload": {
          "$ref": "#/definitions/RemoveUserAccountDataPayload"
        },
        "setUserAccountDataPayload": {
          "$ref": "#/definitions/SetUserAccountDataPayload"
        },
        "updateUserAccountDataPayload": {
          "$ref": "#/definitions/UpdateUserAccountDataPayload"
        }
      },
      "required": [
        "setUserAccountDataPayload",
        "updateUserAccountDataPayload",
        "removeUserAccountDataPayload"
      ],
      "type": "object"
    },
    "SessionStatus": {
      "enum": [
        "FAILED",
        "RESTRICTED",
        "SUCCESSFUL",
        "null"
      ],
      "type": "string"
    },
    "SetUserAccountDataPayload": {
      "additionalProperties": false,
      "properties": {
        "data": {
          "$ref": "#/definitions/UserAccountData"
        },
        "type": {
          "type": "string"
        },
        "version": {
          "type": "string"
        }
      },
      "required": [
        "data",
        "type",
        "version"
      ],
      "type": "object"
    },
    "UpdateUserAccountDataPayload": {
      "additionalProperties": false,
      "properties": {
        "data": {
          "$ref": "#/definitions/AtLeastOne%3CUserAccountData%3E"
        },
        "type": {
          "type": "string"
        },
        "version": {
          "type": "string"
        }
      },
      "required": [
        "data",
        "type",
        "version"
      ],
      "type": "object"
    },
    "UserAccountData": {
      "additionalProperties": false,
      "properties": {
        "firstTimeDeposited": {
          "type": "boolean"
        },
        "kycState": {
          "$ref": "#/definitions/VerificationStatus"
        },
        "lastDepositedAt": {
          "type": "string"
        },
        "sessionStatus": {
          "$ref": "#/definitions/SessionStatus"
        },
        "userId": {
          "type": "string"
        }
      },
      "required": [
        "userId",
        "sessionStatus",
        "kycState",
        "firstTimeDeposited",
        "lastDepositedAt"
      ],
      "type": "object"
    },
    "VerificationStatus": {
      "enum": [
        "EXPIRED",
        "PENDING",
        "TEMPORARY",
        "UNVERIFIED",
        "VERIFIED"
      ],
      "type": "string"
    }
  }
}

有什么线索吗?我还没法让它工作。

解决方案

本回答将聚焦于 schema.definitions.SetUserAccountDataPayload,但对于你的每个示例,原理都是一样的。

schema.definitions.SetUserAccountDataPayload 就是这个对象:

{
  "additionalProperties": false,
  "properties": {
    "data": {
      "$ref": "#/definitions/UserAccountData"
    },
    "type": {
      "type": "string"
    },
    "version": {
      "type": "string"
    }
  },
  "required": [
    "data",
    "type",
    "version"
  ],
  "type": "object"
}

所以当你调用 ajv.compile(schema.definitions.SetUserAccountDataPayload) 时,等同于执行以下操作:

ajv.compile({
  additionalProperties: false,
  properties: {
    data: {
      $ref: '#/definitions/UserAccountData',
    },
    type: {
      type: 'string',
    },
    version: {
      type: 'string',
    },
  },
  required: ['data', 'type', 'version'],
  type: 'object',
});

但是 #/definitions/UserAccountData 在该对象中无法解析——里面甚至没有一个 definitions 属性。

相反,你可以把整个 schema 编译,然后使用 getSchema 提取你想要的特定子模式的验证器:

const ajv = new Ajv();

ajv.compile(schema); // or do this during construction: `new Ajv({ schemas: [schema] })`

const validate = ajv.getSchema<SetUserAccountDataPayload>(
  '#/definitions/SetUserAccountDataPayload',
);

或者,你也可以把 cross-platform-bridge.types.json 拆分成多个模式。有关更多信息,请参阅Ajv的“组合模式”指南:Ajv的“组合模式”指南

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章