2

我想将一个对象作为 HTTP 响应返回,其中一个字段可以为空。问题是 proto3 不会让我轻易做到。发生这种情况是因为我将字符串指针解析为字符串,因此当指针指向 null 时会产生此错误 runtime error: invalid memory address or nil pointer dereference

我试图通过至少从互联网上学到的这两种变通方法来解决这个问题。

1.使用一个

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 结构以适应原始消息)

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 结构以适应原始消息)

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 响应定义一个可为空的字段,以及如何从 struct 中解析它。谢谢!

4

2 回答 2

1

事实证明,我找到了另一种真正有效的解决方法!它正在使用 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 结构以适应原始消息)

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,
            }
        }
于 2019-09-13T11:25:41.647 回答
0

我假设你设置了syntax = proto3;. 我认为目前没有办法实现您所追求的目标。去检查这个问题

但如果你愿意与

{"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)
}
// ...
于 2019-09-12T17:33:37.270 回答