如何使用go-mongo-driver将BSON字符串值解组为自定义类型?

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

How to unmarshal a BSON string value into a custom type using go-mongo-driver?

问题

我正在使用MarshalBSONValue将内部结构字段编组为自定义字符串表示形式。

我无法弄清楚如何实现逆操作UnmarshalBSONValue,以便将自定义字符串表示形式解析为内部结构。

  1. import (
  2. "fmt"
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "go.mongodb.org/mongo-driver/bson"
  6. "go.mongodb.org/mongo-driver/bson/bsontype"
  7. )
  8. type inner struct {
  9. value string
  10. }
  11. func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
  12. return bsontype.String, []byte(i.value), nil
  13. }
  14. // How to implement this?
  15. //
  16. // func (i *inner) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
  17. // ...
  18. // }
  19. type Outer struct {
  20. Inner inner `bson:"inner"`
  21. }
  22. func TestMarshalBSON(t *testing.T) {
  23. var outer1 = Outer{Inner: inner{value: "value"}}
  24. doc, err := bson.Marshal(outer1)
  25. assert.NoError(t, err)
  26. fmt.Printf("%#v\n", string(doc)) // "\x11\x00\x00\x00\x02inner\x00value\x00"
  27. var outer2 Outer
  28. err = bson.Unmarshal(doc, &outer2) // error
  29. assert.NoError(t, err)
  30. assert.Equal(t, outer1, outer2)
  31. }

如果有人能够为上述示例测试提供一个可行的UnmarshalBSONValue实现,我将非常感激。

英文:

I'm using MarshalBSONValue to marshal an inner struct field to a custom string representation.

I can't figure out how to implement the inverse operation, UnmarshalBSONValue, in order to parse the custom string representation into an inner struct.

  1. import (
  2. "fmt"
  3. "testing"
  4. "github.com/stretchr/testify/assert"
  5. "go.mongodb.org/mongo-driver/bson"
  6. "go.mongodb.org/mongo-driver/bson/bsontype"
  7. )
  8. type inner struct {
  9. value string
  10. }
  11. func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
  12. return bsontype.String, []byte(i.value), nil
  13. }
  14. // How to implement this?
  15. //
  16. // func (i *inner) UnmarshalBSONValue(t bsontype.Type, data []byte) error {
  17. // ...
  18. // }
  19. type Outer struct {
  20. Inner inner `bson:"inner"`
  21. }
  22. func TestMarshalBSON(t *testing.T) {
  23. var outer1 = Outer{Inner: inner{value: "value"}}
  24. doc, err := bson.Marshal(outer1)
  25. assert.NoError(t, err)
  26. fmt.Printf("%#v\n", string(doc)) // "\x11\x00\x00\x00\x02inner\x00value\x00"
  27. var outer2 Outer
  28. err = bson.Unmarshal(doc, &outer2) // error
  29. assert.NoError(t, err)
  30. assert.Equal(t, outer1, outer2)
  31. }

I would greatly appreciate it if anyone could provide a working implementation of UnmarshalBSONValue for the example test above.

答案1

得分: 4

你可以使用bsoncore.ReadString来解析给定的值。

  1. func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
  2. return bson.MarshalValue(i.value)
  3. }
  4. func (i *inner) UnmarshalBSONValue(t bsontype.Type, value []byte) error {
  5. if t != bsontype.String {
  6. return fmt.Errorf("无效的 bson 值类型 '%s'", t.String())
  7. }
  8. s, _, ok := bsoncore.ReadString(value)
  9. if !ok {
  10. return fmt.Errorf("无效的 bson 字符串值")
  11. }
  12. i.value = s
  13. return nil
  14. }
英文:

You can use bsoncore.ReadString to parse the given value.

  1. func (i inner) MarshalBSONValue() (bsontype.Type, []byte, error) {
  2. return bson.MarshalValue(i.value)
  3. }
  4. func (i *inner) UnmarshalBSONValue(t bsontype.Type, value []byte) error {
  5. if t != bsontype.String {
  6. return fmt.Errorf("invalid bson value type '%s'", t.String())
  7. }
  8. s, _, ok := bsoncore.ReadString(value)
  9. if !ok {
  10. return fmt.Errorf("invalid bson string value")
  11. }
  12. i.value = s
  13. return nil
  14. }

huangapple
  • 本文由 发表于 2021年7月18日 12:29:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/68426012.html
匿名

发表评论

匿名网友

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

确定