在顶层使用oneOf / anyOf时Fastify无法序列化响应架构

问题描述

这是我的路线:

fastify.route({
    method: "GET",url: "/foo/:foo_id",schema: {
        params: {
            foo_id: { type: "string" },},response: {
            200: {
                oneOf: [
                    { type: "string" },{ type: "number" },],handler: fooHandler,})

当我尝试启动服务器时,出现以下错误消息:

{
    "code":"FST_ERR_SCH_SERIALIZATION_BUILD","message":"Failed building the serialization schema for GET: /foo/:foo_id,due to error undefined unsupported","statusCode":500,"stack":"FastifyError: Failed building the serialization schema for GET: /foo/:foo_id,due to error undefined unsupported
        at Boot.<anonymous> (/home/fooUser/repo/node_modules/fastify/lib/route.js:280:19)
        at Object.onceWrapper (events.js:421:28)
        at Boot.emit (events.js:327:22)
        at /home/fooUser/repo/node_modules/avvio/boot.js:153:12
        at /home/fooUser/repo/node_modules/avvio/plugin.js:269:7
        at done (/home/fooUser/repo/node_modules/avvio/plugin.js:201:5)
        at check (/home/fooUser/repo/node_modules/avvio/plugin.js:225:9)
        at internal/process/task_queues.js:153:7
        at AsyncResource.runInAsyncScope (async_hooks.js:186:9)
        at AsyncResource.runMicrotask (internal/process/task_queues.js:150:8)
        at processticksAndRejections (internal/process/task_queues.js:97:5)"
}

我在架构定义中没有发现任何错误。似乎它不仅适用于响应模式。我为bodyfoo_id尝试了相同的模式,并且运行正常:

params: {
    foo_id: {
        oneOf: [
            { type: "string" },}
},body: {
    oneOf: [
        { type: "string" },]
}

当我在响应模式中使用oneOf但处于嵌套级别时,它也可以工作,就像这样:

response: {
    200: {
        type: "object",properties: {
            foo: {
                oneOf: [
                    { type: "string" },}
        }
    },}

我不明白为什么我不能为http响应定义多个架构,这没有道理。

解决方法

问题在于fast-json-stringify不支持oneOf作为根对象:

const fastJson = require('fast-json-stringify')

const serial = fastJson({
  type: 'object',properties: {
    response: {
      oneOf: [
        { type: "string" },{ type: "number" },],}
  }
})

console.log(serial(5));
console.log(serial("5"));

因此,您有两种解决方案:

  1. 向模块发送PR以添加此功能?

  2. 将纯字符串/数字属性包装到对象上:

fastify.get('/',{
  schema: {
    response: {
      200: {
        type: 'object',properties: {
          response: {
            oneOf: [
              { type: "string" },}
        }
      },},}
},...
  1. 在处理程序中为这些特殊情况编写自定义序列化器:
const fastify = require('fastify')({ logger: true })
fastify.get('/',{
  serializerCompiler({ schema,method,url,httpStatus }) {
    return (responsePayload) => {
      if (typeof responsePayload === 'string') {
        return `"${responsePayload}"`
      } else {
        return `${responsePayload}`
      }
    }
  },schema: {
    response: {
      200: {
        oneOf: [
          { type: "string" },}
    },handler: async () => { return Math.random() >= 0.5 ? 5 : '5' }
})

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...