Decoding nested serialized JSON
Nevon opened this issue · 1 comments
I have a situation where I'm receiving a JSON event where one field contains a string containing serialized JSON. I would like to build a decoder that decodes the outer event as well as the nested serialized JSON string. Some pseudo-code to show what I mean:
const history = JSON.stringify({ employment: ["Captain of Costa Concordia", "Designer of the Vasa"] })
const event = {
name: 'John Smith',
age: 34,
history
}
const decoder = object({
name: nonEmptyString,
age: positiveInteger,
history: serializedJson(object({
employment: array(string)
}))
})
const parsed = decoder.verify(event)
console.log(parsed.history.employment[0]) // "Captain of Costa Concordia"
I went through the documentation on how to construct your own decoders, and I got it to work at runtime, but the resulting Typescript type is not quite right:
function serializedJson<T>(decoder: Decoder<T>): Decoder<T> {
return nonEmptyString.transform(value => JSON.parse(value)).then(decoder.decode)
}
The result of this is that the event I defined above would complain about my history
field being a string instead of an object, which makes sense since serializedJson<T>
has a return type of Decoder<T>
, but then I'm clearly missing how I can express that I expect the input type to be of type string
but the return type from verify
should be T
.
Any guidance would be appreciated. 🙂
Actually, I think this works exactly how it's supposed to. It's just a limitation that's already documented:
From the type definition, you can always tell what the decoder will return. You cannot tell from the type what input values it will accept.
Where I confused myself was by doing something like:
type Event = ReturnType<typeof decoder.verify>
const event = {
name: 'John Smith',
age: 34,
// TS complains here because it's supposed to be an object, not a string
// which is fair enough since the _output_ type is an object
history: JSON.stringify({ employment: ["Captain of Costa Concordia", "Designer of the Vasa"] })
}