编组为 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()功能非常相似。

但是,更一般地说,如何在 MarshalUnmarshaling 期间从类型 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 接口来对解组执行相同的操作