在顶层使用 oneOf / anyOf 时,Fastify 无法序列化响应模式
Fastify fail to serialize response schema when using oneOf / anyOf at top level
这是我的路线:
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)"
}
我的架构定义没有发现任何错误。它似乎不仅仅适用于响应模式。我为 body
和 foo_id
尝试了相同的模式并且它工作正常:
params: {
foo_id: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
},
body: {
oneOf: [
{ type: "string" },
{ type: "number" },
]
}
当我在响应模式中但在嵌套级别使用 oneOf
时它也有效,如下所示:
response: {
200: {
type: "object",
properties: {
foo: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
}
},
}
我不明白为什么我不能为 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"));
所以你有几个解决方案:
向模块发送 PR 以添加此功能
将普通的 string/number 道具包裹到一个对象中:
fastify.get('/', {
schema: {
response: {
200: {
type: 'object',
properties: {
response: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
}
},
},
}
},...
- 在您的处理程序中为这些特殊情况编写自定义序列化程序:
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" },
{ type: "number" },
],
}
},
},
handler: async () => { return Math.random() >= 0.5 ? 5 : '5' }
})
这是我的路线:
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)"
}
我的架构定义没有发现任何错误。它似乎不仅仅适用于响应模式。我为 body
和 foo_id
尝试了相同的模式并且它工作正常:
params: {
foo_id: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
},
body: {
oneOf: [
{ type: "string" },
{ type: "number" },
]
}
当我在响应模式中但在嵌套级别使用 oneOf
时它也有效,如下所示:
response: {
200: {
type: "object",
properties: {
foo: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
}
},
}
我不明白为什么我不能为 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"));
所以你有几个解决方案:
向模块发送 PR 以添加此功能
将普通的 string/number 道具包裹到一个对象中:
fastify.get('/', {
schema: {
response: {
200: {
type: 'object',
properties: {
response: {
oneOf: [
{ type: "string" },
{ type: "number" },
],
}
}
},
},
}
},...
- 在您的处理程序中为这些特殊情况编写自定义序列化程序:
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" },
{ type: "number" },
],
}
},
},
handler: async () => { return Math.random() >= 0.5 ? 5 : '5' }
})