Object key/value order changes after parsing #1852
-
This seems like an odd behavior, and I don't know if this is intended or not. When using Example: const Schema = z.object({
one: z.number(),
two: z.number(),
three: z.number(),
})
const data = { three: 3, two: 2, one: 1 };
Schema.parse(data) // returns { one: 1, two: 2, three: 3 } Is there a workaround for this? In my case the order of the key/values is very important because we are using the data object as a signature message, and if the order changes at all, then the signature will be different. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 8 replies
-
It seems that the order of the keys is determined by the schema not the value passed to Does this help? const schema = z.object( {
three: z.number(),
two: z.number(),
one: z.number(),
} )
console.log( schema.parse( {
one: 1,
three: 3,
two: 2,
} ) )
// { three: 3, two: 2, one: 1 } |
Beta Was this translation helpful? Give feedback.
-
I took another look at it and found that you could do this potentially. This way preserves the order of keys from the passed value. const schema = z.record( z.enum( [ 'one', 'two', 'three' ] ), z.number() )
console.log( schema.parse( {
three: 3,
two: 2,
one: 1,
} ) )
// { three: 3, two: 2, one: 1 } |
Beta Was this translation helpful? Give feedback.
-
How about this? const schema = z.custom( value =>
z.object( {
one: z.number(),
two: z.number(),
three: z.number(),
} ).safeParse( value ).success
)
console.log( schema.parse( {
three: 3,
two: 2,
one: 1,
} ) )
// { three: 3, two: 2, one: 1 } |
Beta Was this translation helpful? Give feedback.
-
This way keeps the type safety. Does this work for you? function returnDataInSameOrderAsPassed<Schema extends z.ZodObject<z.ZodRawShape>> (
schema: Schema
) {
return z.custom( value => schema.safeParse( value ).success ) as Schema
// return z.custom<z.infer<Schema>>( value => schema.safeParse( value ).success )
// this could also work ^^^^^^
}
const objSchema = z.object( {
one: z.number(),
two: z.number(),
three: z.number(),
} )
console.log( objSchema.parse( {
three: 3,
two: 2,
one: 1,
} ) )
// { one: 1, two: 2, three: 3 }
const sameOrderAsPassedSchema = returnDataInSameOrderAsPassed( objSchema )
type SameOrderAsPassedSchema = z.infer<typeof sameOrderAsPassedSchema>
// type SameOrderAsPassedSchema = {
// one: number
// two: number
// three: number
// }
console.log( sameOrderAsPassedSchema.parse( {
three: 3,
two: 2,
one: 1,
} ) )
// { three: 3, two: 2, one: 1 } |
Beta Was this translation helpful? Give feedback.
This way keeps the type safety. Does this work for you?