Protobuf生成Go结构体JSON反序列化字段名不匹配,如何转为驼峰?
问题描述
我有如下Protobuf定义:
message HeaderAttributes { int32 page_count = 1; int32 total_count = 2; } message Header { HeaderAttributes header_attributes = 1; }
使用protoc生成对应的Go结构体后,结构体的JSON标签为下划线格式:
type Header struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields HeaderAttributes *HeaderAttributes `protobuf:"bytes,1,opt,name=header_attributes,json=headerAttributes,proto3" json:"header_attributes,omitempty"` } type HeaderAttributes struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields PageCount int32 `protobuf:"varint,1,opt,name=page_count,json=pageCount,proto3" json:"page_count,omitempty"` TotalCount int32 `protobuf:"varint,2,opt,name=total_count,json=totalCount,proto3" json:"total_count,omitempty"` }
尝试反序列化如下JSON HTTP响应时,因字段名不匹配失败:
"header": { "headerAttributes": { "pageCount": 1, "totalCount": 1 } }
请问如何将生成的结构体字段名转换为驼峰格式?
解决方案
方法1:修改Protobuf定义指定JSON字段名
在Protobuf字段中通过json_name选项直接指定驼峰格式的字段名,重新生成Go代码后,结构体的JSON标签会自动匹配目标格式。修改后的Protobuf定义:
message HeaderAttributes { int32 page_count = 1 [json_name = "pageCount"]; int32 total_count = 2 [json_name = "totalCount"]; } message Header { HeaderAttributes header_attributes = 1 [json_name = "headerAttributes"]; }
方法2:通过protoc-gen-go参数自动生成驼峰JSON标签
执行protoc命令时添加json_tag参数,让生成的Go结构体自动将下划线命名的字段转换为驼峰格式的JSON标签,无需修改Protobuf定义。命令示例:
protoc --go_out=. --go_opt=paths=source_relative --go_opt=json_tag=json:. your_proto_file.proto
方法3:自定义JSON反序列化(不推荐)
如果无法重新生成代码,可以为结构体实现UnmarshalJSON方法手动处理字段映射,但这种方式维护成本较高。示例代码:
func (h *Header) UnmarshalJSON(data []byte) error { type Alias Header aux := &struct { HeaderAttributes *HeaderAttributes `json:"headerAttributes"` *Alias }{ Alias: (*Alias)(h), } if err := json.Unmarshal(data, aux); err != nil { return err } h.HeaderAttributes = aux.HeaderAttributes return nil } func (ha *HeaderAttributes) UnmarshalJSON(data []byte) error { type Alias HeaderAttributes aux := &struct { PageCount int32 `json:"pageCount"` TotalCount int32 `json:"totalCount"` *Alias }{ Alias: (*Alias)(ha), } if err := json.Unmarshal(data, aux); err != nil { return err } ha.PageCount = aux.PageCount ha.TotalCount = aux.TotalCount return nil }
内容的提问来源于stack exchange,提问作者Aarish Ramesh
相关产品推荐
相关产品推荐

