Using Zod with LHS brackets (validating query strings) #1244
-
|
Hello, consider the following schema, in particular the shipmentDate field: export const getShipmentsSchema = object({
query: object({
previous: string(),
next: string(),
shipmentDate: string()
.refine((date) => spacetime(date).isValid(),
{message:"Invalid date supplied"}).transform(date => new Date(spacetime(date, 'UTC').epoch))
})})After having read about REST API filtering/ sorting I have found a specific library, namely QS, that takes in a query string and performs the following: qs.parse('shipmentDate[gte]=2022-11-02&shipmentDate[lte]=2022-11-20';This automagically produces the following: { shipmentDate: { gte: '2022-11-02', lte: '2022-11-20' } }Which would be truly amazing if I could make this work with Zod, as it would give the shipmentDate the filtering power without having to add more fields, would benefit from Zod's validation and would be ready to go directly as a DB request. Is there any way to make this work with the Zod schema provided above? Ideally, a field would be:
I was considering maybe .preprocess(), but no idea how to incorporate that in the provided schema. Could you kindly provide any ideas/ examples, please? Thank you! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
|
A solution could be the following: const schema = z.string().transform((val) => {
const args = val.split("&");
if (args.length === 0) {
return null;
}
const map: Record<string, any> = {};
const s = z.object({
shipmentDate: z.object({
gte: z.string(),
lte: z.string(),
}),
});
for (const arg of args) {
const [name, value] = arg.split("=");
if (name.match(/[a-zA-Z]*\[[a-zA-Z]*\]/)) {
let [lonelyName, x] = name.split("[");
x = x.split("]")[0];
if (lonelyName in map) {
map[lonelyName][x] = value;
} else {
map[lonelyName] = {
[x]: value,
};
}
} else {
return null;
}
}
return s.parse(map);
});
/** data is of type
*
* {
* shipmentDate: {
* gte: string;
* lte: string;
* };
* } | null
*
*/
const data = schema.parse(
"shipmentDate[gte]=2022-11-02&shipmentDate[lte]=2022-11-20",
); But this is not versatile, because you have to define the schema inside the You could also add a |
Beta Was this translation helpful? Give feedback.
A solution could be the following: