You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GRPC-gateway(Golang):如何在JSON响应中实现部分字段返回null、部分字段为空时省略

GRPC-gateway(Golang):如何在JSON响应中实现部分字段返回null、部分字段为空时省略

我完全理解你的困扰——既要让某些字段在为空时直接从JSON响应里消失,又要让另一些字段哪怕是空值也必须显示null,还不能修改现有的Proto结构,默认的JSONPb配置根本没法同时满足这两个需求对吧?

别担心,我们可以通过自定义JSON marshaler来解决这个问题,不需要改动任何Proto定义,只需要在Go代码里做一层包装处理就行。

核心思路

默认的JSONPb要么开启EmitUnpopulated: true(所有未设置的字段都输出null),要么关闭它(所有未设置的字段都省略),没法针对单个字段做差异化处理。我们的解决办法是:

  1. 先开启EmitUnpopulated: true序列化,确保需要显示null的字段(也就是nullableValue)能正常输出null;
  2. 序列化完成后,手动修改JSON结果,把需要省略的字段(reallyOptionalValue)如果是null或者空字符串的话,从JSON对象中移除。

代码实现

首先,我们定义一个自定义的marshaler,嵌入原生的runtime.JSONPb,然后重写它的Marshal方法:

import (
	"encoding/json"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/protobuf/encoding/protojson"
	// 导入你的proto生成的包,比如:
	// pb "your/project/path/proto"
)

type CustomJSONMarshaler struct {
	runtime.JSONPb
}

func (m *CustomJSONMarshaler) Marshal(v interface{}) ([]byte, error) {
	// 先用默认的JSONPb规则序列化(开启EmitUnpopulated,保证nullableValue输出null)
	rawData, err := m.JSONPb.Marshal(v)
	if err != nil {
		return nil, err
	}

	// 只处理我们关心的Response类型,其他类型直接返回原始结果
	resp, ok := v.(*pb.Response)
	if !ok {
		return rawData, nil
	}

	// 把JSON解析成map,方便修改字段
	var jsonObj map[string]interface{}
	if err := json.Unmarshal(rawData, &jsonObj); err != nil {
		return nil, err
	}

	// 处理reallyOptionalValue:如果值是null或者空字符串,就从JSON中删掉
	if val, exists := jsonObj["reallyOptionalValue"]; exists {
		if val == nil || val == "" {
			delete(jsonObj, "reallyOptionalValue")
		}
	}

	// 把修改后的map重新序列化为JSON
	return json.Marshal(jsonObj)
}

然后,在创建GRPC-Gateway的mux时,使用这个自定义的marshaler:

func main() {
	// 初始化自定义marshaler
	customMarshaler := &CustomJSONMarshaler{
		JSONPb: runtime.JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				EmitUnpopulated: true, // 确保nullableValue未设置时输出null
				UseCamelCase:    true, // 把proto的下划线字段名转成JSON的驼峰命名
			},
		},
	}

	// 创建mux并指定自定义marshaler
	mux := runtime.NewServeMux(
		runtime.WithMarshalerOption(runtime.MIMEWildcard, customMarshaler),
	)

	// 后续的GRPC-Gateway注册逻辑...
}

效果验证

  • 当really_optional_value未设置或者为空字符串时,JSON响应里不会出现reallyOptionalValue字段;
  • 当nullable_value未设置时,JSON响应里会显示"nullableValue": null;
  • 两个字段都有有效值时,会正常输出对应的字符串。

这个方案完全不需要修改你的Proto结构,完美适配你的需求~

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:14:31