Could someone help me to create a HOOK in FASTIFY to automatically serialize these types of values in all app.ts endpoints
I managed to solve the problem using .toString, but I wanted a way to do this automatically in all requests
First of all, bigint is not supported by JS standard functions:
const big = { n: :1231231231231231213n }
console.log(typeof big.n) // bigint
JSON.stringify(big) // TypeError: Do not know how to serialize a BigInt
JSON.parse('{"n":1231231231231231213}') // { n: 1231231231231231200 }
Here is 3 solutions:
preSerialization
hook. Note that the toString
returns a string a not a numbersetReplySerializer
. Different approach but same result as before.I would use something that gives fully control over the serialization, because serializing bigint is not supported by the JSON.*
utilities and the client who parse the json must be aware of it or it will fail!
See the code snippet above, JSON.parse()
trims the number.
const app = require('fastify')({ logger: true })
app.get('/solution-1', {
schema: {
response: {
200: {
type: 'object',
properties: {
n: { type: 'number' }
}
}
}
}
}, async (request, reply) => {
return { n: 1231231231231231213n } // prints {"n":1231231231231231200} (not a string 🚀)
})
app.register(function plugin (app, opts, next) {
app.addHook('preSerialization', async (request, reply, payload) => {
payload.n = payload.n.toString()
return payload
})
app.get('/solution-2', async (request, reply) => {
return { n: 1231231231231231213n } // prints {"n":"1231231231231231213"}
})
next()
})
app.register(function plugin (app, opts, next) {
app.setReplySerializer(function (payload, statusCode) {
return JSON.stringify(payload, (key, value) =>
typeof value === 'bigint'
? value.toString()
: value
)
})
app.get('/solution-3', async (request, reply) => {
return { n: 1231231231231231213n } // prints {"n":"1231231231231231213"}
})
next()
})
app.listen({ port: 8080 })
curl http://localhost:8080/solution-1
curl http://localhost:8080/solution-2
curl http://localhost:8080/solution-3