typescript - How can I transform or preprocess a general field in zod? - Stack Overflow
[Feature Request] Allow preprocess even if schema validation fails
How are people using zod?
reactjs - How to transform object to array before parsing in Zod - Stack Overflow
I have an entity, and it's starting to have several shapes depending on how it's being used:
-
I have a shape of it when I get it back from the API
-
I have another shape of it when in forms (some fields are omitted, while others are transformed -- ie for select/option)
I guess what I'm wondering is how do people handle this? Are they having separate zod definitions for each case? Creating a base and sharing it?
Thanks.
Thanks for the answer @Konrad !
I improved it a little bit in typescript, so it is also typed correctly:
const arrayFromString = <T extends ZodTypeAny>(schema: T) => {
return z.preprocess((obj) => {
if (Array.isArray(obj)) {
return obj;
} else if (typeof obj === "string") {
return obj.split(",");
} else {
return [];
}
}, z.array(schema));
};
I didn't test that, but seems like should work:
const FieldsSchema = z.object({
fullName: z.string(),
type: z.string()
});
export const sObjectMetadataSchema = z.object({
fields: z.union([FieldsSchema, FieldsSchema.array()]).transform((rel) => {
return Array.isArray(rel)
? rel
: [rel];
}),
});
I have the following problem. There is external data coming from an API which I want to store in local database. Before I do that, some transformations of the data need to occur so it matches pre-existing types and structure. For example, if the API returns a response like this one:
[{
id: 1,
name: 'foo',
short_name: 'foo-1',
country: {
id: 1, name: 'UK'
}
},
{
id: 2,
name: 'bar',
short_name: null, // <= missing
country: {
id: 2, name: 'France'
}
}];I need to restructure it like this before adding it to the database:
// data needs to match the database types
type DBPerson = {
id: number;
name: string;
short_name: string;
};
type DBCountry = {
id: number;
name: string;
}
// people
[
{ id: 1, name: 'foo', short_name: 'foo-1' },
{ id: 2, name: 'bar', short_name: 'bar-2' }
];
// countries
[
{ id: 1, name: 'UK' },
{ id: 2, name: 'France' }
];This is where I find Zod limiting, probably because it wasn't built for that particular task.
For example, you will notice short_name in the first object from the demo API response is null, but it could be generated from the values of id and name fields. No easy way to do that with zod unless you use .preprocess.
Another problem is that Zod doesn't provide a native way to define a schema based on a pre-existing type, like z.object<DBPerson>({...}) for example.
Lastly, I could of course process the data myself with .map, .reduce etc., before passing it to Zod but that's more code to maintain, not to mention it would have a performance impact.
So essentially I am looking for a library similar to Zod, but you should be able to do some more advanced transformations before parsing occurs. If someone more experienced with this type of problem has some insight to share, please let me know, thanks!