编组为 json 时转到转换类型
Go Convert type when marshaling to json
我的问题与返回途中的this one, however instead of converting a float64
to a string
which is handled using the string tag. In my case I'm trying to convert a ObjectID
to a string using it's .Hex()
method. And, vice versa using the .FromHex()
功能非常相似。
但是,更一般地说,如何在 Marshal
和 Unmarshal
ing 期间从类型 X
转换为类型 Y
并返回?
我的例子:
package main
import (
"log"
"fmt"
"encoding/json"
"github.com/mongodb/mongo-go-driver/bson/objectid"
)
type Greeting struct {
Id *objectid.ObjectID `json:"id"`
Greeting string `json:"greeting,omitempty"`
}
func main() {
// Create ObjectID
id, err := objectid.FromHex("5b14dd20f6418c8443a5ffec")
if err != nil { log.Fatal(err) }
// Create Greeting
g := Greeting{&id, "Hello, World!"}
// Marshal to json
j, err := json.Marshal(g)
if err != nil { log.Fatal(err) }
// Print Json
fmt.Printf("Json: %s", string(j))
}
输出:
Json: {"id":[91,20,221,32,246,65,140,132,67,165,255,236],"greeting":"Hello, World!"}
然而,我想要的是:
Json: {"id":"5b14dd20f6418c8443a5ffec","greeting":"Hello, World!"}
您应该编写自己的 (un) 编组函数,在其中处理 conversions/conditions 并将其作为调用 json (un) 编组的参数处理。
type Whatever struct {
someField int
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
SomeField int `json:"some_field"`
}{
SomeField: w.someField,
})
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"some_field": w.SomeField,
})
}
您可以向 objectid.ObjectId
声明一个命名类型,它将实现 json.Marshaler
接口以覆盖标准封送处理并改为输出十六进制字符串:
type Id objectid.ObjectId
func (id Id) MarshalJSON() ([]byte, error) {
return json.Marshal(objectid.ObjectId(id).Hex())
}
并在您的结构中使用它代替 objectid.ObjectId
:
type Greeting struct {
Id Id
Greeting string
}
现在,当您编组 Greeting
时,json 包将按预期编组 Greeting
字段,但是由于 Id
字段实现了 json.Marshaler
,它将由 Id.MarshalJSON
编组,输出 id.Hex()
.
您可以通过为 Id
.
实现 json.Unmarshaler
接口来对解组执行相同的操作
我的问题与返回途中的this one, however instead of converting a float64
to a string
which is handled using the string tag. In my case I'm trying to convert a ObjectID
to a string using it's .Hex()
method. And, vice versa using the .FromHex()
功能非常相似。
但是,更一般地说,如何在 Marshal
和 Unmarshal
ing 期间从类型 X
转换为类型 Y
并返回?
我的例子:
package main
import (
"log"
"fmt"
"encoding/json"
"github.com/mongodb/mongo-go-driver/bson/objectid"
)
type Greeting struct {
Id *objectid.ObjectID `json:"id"`
Greeting string `json:"greeting,omitempty"`
}
func main() {
// Create ObjectID
id, err := objectid.FromHex("5b14dd20f6418c8443a5ffec")
if err != nil { log.Fatal(err) }
// Create Greeting
g := Greeting{&id, "Hello, World!"}
// Marshal to json
j, err := json.Marshal(g)
if err != nil { log.Fatal(err) }
// Print Json
fmt.Printf("Json: %s", string(j))
}
输出:
Json: {"id":[91,20,221,32,246,65,140,132,67,165,255,236],"greeting":"Hello, World!"}
然而,我想要的是:
Json: {"id":"5b14dd20f6418c8443a5ffec","greeting":"Hello, World!"}
您应该编写自己的 (un) 编组函数,在其中处理 conversions/conditions 并将其作为调用 json (un) 编组的参数处理。
type Whatever struct {
someField int
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
SomeField int `json:"some_field"`
}{
SomeField: w.someField,
})
}
func (w Whatever) MarshalJSON() ([]byte, error) {
return json.Marshal(map[string]interface{}{
"some_field": w.SomeField,
})
}
您可以向 objectid.ObjectId
声明一个命名类型,它将实现 json.Marshaler
接口以覆盖标准封送处理并改为输出十六进制字符串:
type Id objectid.ObjectId
func (id Id) MarshalJSON() ([]byte, error) {
return json.Marshal(objectid.ObjectId(id).Hex())
}
并在您的结构中使用它代替 objectid.ObjectId
:
type Greeting struct {
Id Id
Greeting string
}
现在,当您编组 Greeting
时,json 包将按预期编组 Greeting
字段,但是由于 Id
字段实现了 json.Marshaler
,它将由 Id.MarshalJSON
编组,输出 id.Hex()
.
您可以通过为 Id
.
json.Unmarshaler
接口来对解组执行相同的操作