无法将Protobuf解组为types.Struct类型。

huangapple go评论77阅读模式
英文:

Unable to Unmarshall to types.Struct with Protobuf

问题

我正在处理一个旧版的Go应用程序,类型定义方面让我抓狂。

在某个时候,我需要返回一个值,该值的类型是types.Struct(来自github.com/gogo/protobuf/types)。

以下是该函数的签名:

GetDeviceConfig(ctx context.Context, in *DeviceID, opts ...grpc.CallOption) (*types.Struct, error)

我从Postgres数据库(使用GORM)中获取值,使用一个名为"config"的字符串列。它可以是任何类型的JSON。

这只是一个示例:

{"fields":{"A":{"Kind":{"string_value":"B"}},"C":{"Kind":{"string_value":"D"}}}}

当我尝试将其解组为map[string]interface{}时,它完美运行:

err := client.DB.Where("id = ?", id, 0).First(&device).Error
if err != nil && err != gorm.ErrRecordNotFound {
    return nil, err
}

var dat map[string]interface{}

if err := json.Unmarshal([]byte(device.Config), &dat); err != nil {
    panic(err)
}

但是我需要将其转换为types.Struct(有效的protobuf签名,不能更改)。我最好的猜测是这样的:

// 将JSON转换为结构体
s := types.Struct{}
if err := json.Unmarshal([]byte(device.Config), &s); err != nil {
    panic(err)
}
// fmt.Println(s)

但是s是空的,没有填充任何数据。

需要帮助吗?

英文:

I am working on a legacy Go app that it's driving me crazy in terms of type definition.

At some point I need to return a value with the value types.Struct (from github.com/gogo/protobuf/types).

Here is the signature for the function:

GetDeviceConfig(ctx context.Context, in *DeviceID, opts ...grpc.CallOption) (*types.Struct, error)

I'm getting the value from a Postgres database (with GORM) using a string column called "config". It could be any type of JSON.

Just an example:

{"fields":{"A":{"Kind":{"string_value":"B"}},"C":{"Kind":{"string_value":"D"}}}}

When I try to unmarshall to a map[string]interface{} it works like a charm:

err := client.DB.Where("id = ?", id, 0).First(&device).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	var dat map[string]interface{}

	if err := json.Unmarshal([]byte(device.Config), &dat); err != nil {
		panic(err)
	}

but I need to conver it to types.Struct (valid protobuf signature that cannot be changed). My best guess was something like this:

// convert json to struct
	s := types.Struct{}
	if err := json.Unmarshal([]byte(device.Config), &s); err != nil {
		panic(err)
	}
	// fmt.Println(s)

but s is empty. No data is populated.

Any help?

答案1

得分: 1

为了将JSON解组为Struct,你需要使用Unmarshaler,它位于jsonpb包中。以下是一个示例代码:

err := jsonpb.UnmarshalString(device.Config, &s)
[...]

你可以在jsonpb_test.go中找到更多示例。

英文:

In order to unmarshal JSON into a Struct, you need to use Unmarshaler found in the jsonpb package. Something along the following lines should work:

err := jsonpb.UnmarshalString(device.Config, &s)
[...]

You can find further examples in jsonpb_test.go.

huangapple
  • 本文由 发表于 2021年11月3日 02:57:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/69815643.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定