如何在 Proto3 中为 HTTP 响应创建一个可空字段?
How to Make a Nullable Field in Proto3 for a HTTP Response?
我想 return 一个对象作为 HTTP 响应,其中一个字段可以为空。问题是 proto3 不会让我轻易做到。发生这种情况是因为我将字符串指针解析为字符串,因此当指针指向 null 时会产生此错误
runtime error: invalid memory address or nil pointer dereference
我尝试至少通过从 Internet 上学到的这两个解决方法来解决这个问题。
1。使用 oneof
exercise.proto(消息定义)
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
oneof OptionalSubmissionSerial {
string SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
exercise := &Exercise.ExercisesData {
Serial: e.Serial,
Title: e.Title,
OptionalSubmissionSerial: &Exercise.ExercisesData_SubmissionSerial{
SubmissionSerial: *e.SubmissionInfo.LatestSubmissionSerial,
},
}
2。使用 google/protobuf/wrappers.proto
exercise.proto(消息定义)
import "google/protobuf/wrappers.proto";
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
google.protobuf.StringValue SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
exercise := &Exercise.ExercisesData {
Serial: e.Serial,
Title: e.Title,
SubmissionSerial: &wrappers.StringValue{
Value: *e.SubmissionInfo.LatestSubmissionSerial,
},
}
预期结果
两种方式仍然产生相同的错误信息,唯一的区别是它引用的代码行。这就是为什么我如此无助。预期的 HTTP 响应如下所示
{
"status": "success",
"data": [
{
"serial": "EXC-NT2OBHQT",
"title": "Title of Topic Exercise",
"submission_serial": null
}
]
}
我真的希望任何人都可以帮助我找到一种方法来定义 proto3 中用于 Http 响应的可空字段以及如何从结构 中解析它。谢谢!
我假设你设置了 syntax = proto3;
。我认为目前没有办法实现您所追求的目标。去检查 this issue.
但如果你愿意一起生活
{"serial":"serial","title":"title"}
其中 submission_serial
完全缺失,而不是
{"serial":"serial","title":"title","submission_serial":null}
下面的效果还不错
// ...
data := &ExercisesData{Serial: "serial", Title: "title"}
out, err := proto.Marshal(data)
if err != nil {
log.Fatalln("failed to encode: ", err)
}
buf := &bytes.Buffer{}
marshaler := jsonpb.Marshaler{}
err = marshaler.Marshal(buf, data)
data2 := &ExercisesData{}
if err := proto.Unmarshal(out, data2); err != nil {
log.Fatalln("failed to parse: ", err)
}
// ...
事实证明我找到了另一种实际有效的解决方法!它使用 google/protobuf/wrappers.proto 但我必须在映射器中稍微调整一下。这是怎么回事:
exercise.proto(消息定义)
import "google/protobuf/wrappers.proto";
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
google.protobuf.StringValue SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
import "github.com/golang/protobuf/ptypes/wrappers"
exercise := &pbExercise.GetExercisesData{
Serial: e.Serial,
Title: e.Title,
}
if e.SubmissionInfo.LatestSubmissionSerial != nil {
exercise.SubmissionSerial = &wrappers.StringValue{
Value: *e.LatestSubmissionSerial,
}
}
我想 return 一个对象作为 HTTP 响应,其中一个字段可以为空。问题是 proto3 不会让我轻易做到。发生这种情况是因为我将字符串指针解析为字符串,因此当指针指向 null 时会产生此错误
runtime error: invalid memory address or nil pointer dereference
我尝试至少通过从 Internet 上学到的这两个解决方法来解决这个问题。
1。使用 oneof
exercise.proto(消息定义)
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
oneof OptionalSubmissionSerial {
string SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
exercise := &Exercise.ExercisesData {
Serial: e.Serial,
Title: e.Title,
OptionalSubmissionSerial: &Exercise.ExercisesData_SubmissionSerial{
SubmissionSerial: *e.SubmissionInfo.LatestSubmissionSerial,
},
}
2。使用 google/protobuf/wrappers.proto
exercise.proto(消息定义)
import "google/protobuf/wrappers.proto";
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
google.protobuf.StringValue SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
exercise := &Exercise.ExercisesData {
Serial: e.Serial,
Title: e.Title,
SubmissionSerial: &wrappers.StringValue{
Value: *e.SubmissionInfo.LatestSubmissionSerial,
},
}
预期结果
两种方式仍然产生相同的错误信息,唯一的区别是它引用的代码行。这就是为什么我如此无助。预期的 HTTP 响应如下所示
{
"status": "success",
"data": [
{
"serial": "EXC-NT2OBHQT",
"title": "Title of Topic Exercise",
"submission_serial": null
}
]
}
我真的希望任何人都可以帮助我找到一种方法来定义 proto3 中用于 Http 响应的可空字段以及如何从结构 中解析它。谢谢!
我假设你设置了 syntax = proto3;
。我认为目前没有办法实现您所追求的目标。去检查 this issue.
但如果你愿意一起生活
{"serial":"serial","title":"title"}
其中 submission_serial
完全缺失,而不是
{"serial":"serial","title":"title","submission_serial":null}
下面的效果还不错
// ...
data := &ExercisesData{Serial: "serial", Title: "title"}
out, err := proto.Marshal(data)
if err != nil {
log.Fatalln("failed to encode: ", err)
}
buf := &bytes.Buffer{}
marshaler := jsonpb.Marshaler{}
err = marshaler.Marshal(buf, data)
data2 := &ExercisesData{}
if err := proto.Unmarshal(out, data2); err != nil {
log.Fatalln("failed to parse: ", err)
}
// ...
事实证明我找到了另一种实际有效的解决方法!它使用 google/protobuf/wrappers.proto 但我必须在映射器中稍微调整一下。这是怎么回事:
exercise.proto(消息定义)
import "google/protobuf/wrappers.proto";
message ExercisesData {
string Serial = 1 [json_name="serial"];
string Title = 2 [json_name="title"];
google.protobuf.StringValue SubmissionSerial = 3 [json_name="submission_serial"];
}
mapper.go(解析 Go 结构以适应 proto 消息)
import "github.com/golang/protobuf/ptypes/wrappers"
exercise := &pbExercise.GetExercisesData{
Serial: e.Serial,
Title: e.Title,
}
if e.SubmissionInfo.LatestSubmissionSerial != nil {
exercise.SubmissionSerial = &wrappers.StringValue{
Value: *e.LatestSubmissionSerial,
}
}