Как демонтировать JSON в protobuf, содержащий одно из определений, используя jsonpb? - PullRequest
0 голосов
/ 04 июля 2018

В настоящее время мне не удается разархивировать фрагмент JSON, сгенерированный jsonpb . Может быть, это просто какое-то недоразумение с моей стороны, но, глядя на тесты, я ожидаю, что оно как-то сработает.

Вот соответствующий фрагмент pb.proto:

syntax = "proto3";
package pb;

message Parameter {
    string name = 1;
    oneof value {
        string str_value = 2;
        int32 int_value = 3;
        bool bool_value = 4;
        float float_value = 5;
    }
}

message ParameterSet {
    bytes raw = 1;
    repeated Parameter parameters = 2;
}

message ParameterSets {
    map<string,ParameterSet> sets = 1;
}

Проверка маршалинга / демаршалинга с помощью этого простого фрагмента не удалась:

package main

import (
    "fmt"
    "github.com/gogo/protobuf/jsonpb"
    "strings"
)

func main() {
    m := jsonpb.Marshaler{}
    str, err := m.MarshalToString(&pb.ParameterSets{Sets: map[string]*pb.ParameterSet{
        "parameter": {
            Raw: []byte{0, 1, 2, 3, 4, 5, 6, 1, 2},
            Parameters: []*pb.Parameter{
                {Name: "itest", Value: &pb.Parameter_IntValue{42}},
                {Name: "stest", Value: &pb.Parameter_StrValue{"Foobar"}},
                {Name: "btest", Value: &pb.Parameter_BoolValue{true}},
                {Name: "ftest", Value: &pb.Parameter_FloatValue{41.99}},
           },
        },
    }},)
    fmt.Println(str)
    fmt.Println(err)

    sets := pb.ParameterSets{}
    err = jsonpb.Unmarshal(strings.NewReader(str), &sets)
    fmt.Println(sets)
    fmt.Println(err)
}

Результат:

{"sets":{"parameter":{"raw":"AAECAwQFBgEC","parameters":[{"name":"itest","intValue":42},{"name":"stest","strValue":"Foobar"},{"name":"btest","boolValue":true},{"name":"ftest","floatValue":41.99}]}}}
<nil>
{map[]}
unknown field "intValue" in pb.Parameter

Как я могу получить значения oneof обратно в объекте proto?

1 Ответ

0 голосов
/ 06 июля 2018

Тип перепутан из-за двух папок вендора. Тип, объявленный в двух папках поставщика, является не одинаковым, даже если код для них точно такой же .

Так, например: prototest-master/vendor/github.com/gogo/proto/messageSet (A) не относится к типу prototest-master/ proto /vendor/github.com/gogo/proto/messageSet (B), даже если их импорт такой же (github.com/gogo/proto)

В main.go вашего проекта при построении маршалера jsonpb.Marshaler{} используются типы из (A), где фактические сообщения, такие как &pb.ParameterSets{..., используют типы из (B) для построения себя.

Поскольку jsonpb, кажется, делает много отражений, это нарушает смешение двух типов.

Лучшее решение - использовать только одну папку vendor, чтобы понять, какие типы используются всеми. Я бы просто отказался от папки (B) vendor, потому что она ничего не добавляет.

...