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

gRPC布尔字段值为false时未返回的问题咨询

Protobuf序列化bool默认值字段丢失问题解决

问题原因

这是Protobuf JSON序列化的默认行为:值为类型默认值的字段会被自动省略。bool类型的默认值是false,所以当is_completed为false时,JSON输出中不会包含该字段;而true属于非默认值,因此能正常显示。

解决方案

方案1:修改Protobuf定义(推荐)

在proto3语法中,给is_completed字段添加optional修饰,Protobuf会将其视为“显式设置”的字段,即使值为默认的false,也会在JSON中输出:

message GetTodosResponse {
    repeated Todo todos = 1;
    message Todo {
        int64 id = 1;
        string title = 2;
        optional bool is_completed = 3; // 添加optional标记
    }
}

修改后重新生成Go代码,调用接口时就能得到包含isCompleted: false的完整响应。

方案2:自定义JSON序列化配置

如果无法修改Protobuf定义,可以在Go代码中使用protojson库,通过配置强制输出所有字段(包括默认值):

import "google.golang.org/protobuf/encoding/protojson"

// 构造响应后手动序列化
resp := &desc.GetTodosResponse{Todos: todosResp}
jsonData, err := protojson.MarshalOptions{
    EmitUnpopulated: true, // 开启输出默认值字段
}.Marshal(resp)
if err != nil {
    return nil, err
}
// 后续将jsonData作为响应返回(需适配你的服务框架)

如果使用gRPC-Gateway等网关工具,可以在网关配置中开启对应选项,或替换默认序列化器实现此逻辑。

方案3:排查数据库读取逻辑

确认从数据库读取的todo.IsCompleted确实为false(而非未初始化状态),可通过打印日志验证:

// 在循环内打印读取到的todo数据
for _, todo := range todos {
    fmt.Printf("DB Todo: ID=%d, Title=%s, IsCompleted=%t\n", todo.ID, todo.Title, todo.IsCompleted)
    todosResp = append(todosResp, &desc.GetTodosResponse_Todo{
        Id:          todo.ID,
        Title:       todo.Title,
        IsCompleted: todo.IsCompleted,
    })
}

内容的提问来源于stack exchange,提问作者Sevy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:16:06