Перейти конвертировать тип при маршалинге в JSON - PullRequest
0 голосов
/ 05 июня 2018

Мой вопрос очень похож на этот , однако вместо преобразования float64 в string, который обрабатывается с использованием строкового тега .В моем случае я пытаюсь преобразовать ObjectID в строку, используя метод .Hex().И наоборот, используя функцию .FromHex() на обратном пути.

Однако, в более общем смысле, как преобразовать тип X в тип Y и обратно во время Marshal & Unmarshal ing?

Мой пример:

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!"}

Ответы [ 2 ]

0 голосов
/ 05 июня 2018

Вы можете объявить именованный тип как 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().

Вы можете сделать то же самое для демаршалинга, реализовав интерфейс json.Unmarshaler для Id.

0 голосов
/ 05 июня 2018

Вы должны написать свою собственную (не) функцию маршаллинга, в которой вы обрабатываете ваши преобразования / условия и обрабатываете это как аргумент при вызове json (не) маршаллинга.

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,
   })
}
...