GraphQL查询/变更中的字段大小写转换问题求助
问题场景与需求
技术栈:PostgreSQL(数据库采用snake_case字段命名)、Knex(数据库构建工具)、GraphQL(API采用camelCase字段命名)、Vue.js(前端)
核心问题:数据库字段为local_entrega这类snake_case格式,但GraphQL API定义使用localEntrega这类camelCase格式,导致多单词字段返回null。无法将API改为snake_case,手动字段映射效率低下,寻求自动转换的最优方案。
相关代码示例
查询Resolver
cotacoesLoad: async (_root, _args, ctx, _info) => { return ctx.database('cotacoes') },
关联表Resolver
cliente: async (root, _args, ctx, _info) => { return ctx.database('erp_clientes').where({ id: root.cliente_id }).first() }
GraphQL类型定义
type Cotacao { id: String! cliente: ErpCliente! situacao: Int localEntrega: Int amostraInicial: String lotePiloto: String producao: String ferramental: String dataEnvio: LocalDate nrCotacaoCliente: Int } extend type Query { cotacoesLoad: [Cotacao!]! }
查询结果示例
{ "data": { "cotacoesLoad": [ { "cliente": { "nome": "mestre" }, "situacao": 1, "localEntrega": null, "amostraInicial": null, "lotePiloto": null, "producao": "produ", "ferramental": "a", "dataEnvio": null, "nrCotacaoCliente": null } ] } }
最优解决方案
方法1:Knex全局配置自动转换
利用Knex的postProcessResponse钩子,全局统一将查询结果的snake_case字段转为camelCase,一劳永逸。
const knex = require('knex')({ client: 'pg', connection: { /* 你的数据库连接配置 */ }, // 全局结果转换钩子 postProcessResponse: (result) => { if (Array.isArray(result)) { return result.map(convertToCamelCase); } return convertToCamelCase(result); } }); // 辅助转换函数:snake_case → camelCase function convertToCamelCase(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } const camelCaseObj = {}; Object.keys(obj).forEach(key => { const camelKey = key.replace(/_([a-z])/g, (match, char) => char.toUpperCase()); camelCaseObj[camelKey] = convertToCamelCase(obj[key]); }); return camelCaseObj; }
配置完成后,所有Knex查询返回的结果都会自动适配GraphQL的camelCase字段定义,无需在Resolver中额外处理。
方法2:GraphQL层面批量字段映射
如果不想修改Knex全局配置,可以写一个通用转换函数,在类型Resolver中批量复用:
// 通用映射函数:根据camelCase字段名匹配对应的snake_case数据库字段 const resolveCamelField = (fieldName) => { const snakeCaseField = fieldName.replace(/([A-Z])/g, '_$1').toLowerCase(); return (root) => root[snakeCaseField]; }; // 给Cotacao类型配置批量Resolver const CotacaoResolver = { localEntrega: resolveCamelField('localEntrega'), amostraInicial: resolveCamelField('amostraInicial'), lotePiloto: resolveCamelField('lotePiloto'), dataEnvio: resolveCamelField('dataEnvio'), nrCotacaoCliente: resolveCamelField('nrCotacaoCliente') }; // 将该Resolver关联到你的GraphQL Schema即可
这种方式适合仅需针对特定类型做转换的场景,比手动逐个写映射更高效。
内容的提问来源于stack exchange,提问作者Gustavo Alves
相关产品推荐
相关产品推荐

