如何使用HonoJS从GET请求的URL查询参数中获取嵌套对象
在HonoJS中获取URL查询字符串中的嵌套键值对象
当URL查询参数为cursor[pk]=PK_NAME&cursor[sk]=SK_NAME#1728586654826-c2c67760-d28c-4abe-99f8-2286da2fc5b5这种格式时,直接使用Hono的c.req.query('cursor')或zValidator的z.record会得到undefined,无法自动将分散的cursor[pk]、cursor[sk]合并为嵌套对象,以下是两种可行的解决方案:
方案1:手动解析查询参数
在请求处理器中遍历所有查询参数,提取并组装cursor相关的键值对:
app.get( '/', zValidator( 'query', z.object({ limit: z.coerce.number().int().positive().default(50), order: z.enum(['asc', 'desc']).default('desc'), }) ), async (c) => { const { limit, order } = c.req.valid('query') const cursor = {} // 获取所有查询参数(键对应值数组) const allQueries = c.req.queries() Object.keys(allQueries).forEach(key => { // 匹配cursor[xxx]格式的键 const match = key.match(/^cursor\[(\w+)\]$/) if (match) { const subKey = match[1] // 取数组第一个值(单值场景下) cursor[subKey] = allQueries[key][0] } }) const data = await queryRecords({ cursor, limit, order }) return c.json({ cursor: data.cursor, records: data.records }) } )
方案2:通过Zod预处理器自动合并
利用Zod的preprocess方法,在校验阶段自动从原始查询参数中提取并组装cursor对象:
// 定义cursor的预处理器Schema const cursorSchema = z.preprocess((_, ctx) => { const rawQuery = ctx.data // 获取原始查询参数 const cursor = {} Object.keys(rawQuery).forEach(key => { const match = key.match(/^cursor\[(\w+)\]$/) if (match) { const subKey = match[1] cursor[subKey] = rawQuery[key][0] } }) return cursor }, z.record(z.string(), z.string()).default({})) app.get( '/', zValidator( 'query', z.object({ cursor: cursorSchema, limit: z.coerce.number().int().positive().default(50), order: z.enum(['asc', 'desc']).default('desc'), }) ), async (c) => { const { cursor, limit, order } = c.req.valid('query') const data = await queryRecords({ cursor, limit, order }) return c.json({ cursor: data.cursor, records: data.records }) } )
原因说明
Hono默认的查询参数解析逻辑仅将每个键值对独立存储,不会自动解析key[subkey]这种格式为嵌套对象。因此直接通过c.req.query('cursor')无法获取到值,Zod的z.record也无法识别分散的cursor[pk]、cursor[sk]字段,需要手动处理或通过预处理器合并。
内容的提问来源于stack exchange,提问作者ALFmachine
相关产品推荐
相关产品推荐

