【发布时间】:2017-08-23 09:37:12
【问题描述】:
我有一个类型“书”,我从返回 json 的不同接口读取。读取 json 并处理数据后,我必须将书籍转换为公共书籍类型以隐藏字段并更改输出格式。
我的问题是,来自同一字段 (ISBN) 的输入类型有时是字符串,有时是 int。我认为最简单的解决方案是使用 json.Number 来解组数据。这行得通 - 但我需要不同字段的传出 json 字符串...
这就是我需要帮助的地方。我将有一个自定义类型,我可以在字段的公共结构中设置它,我想将 output-json-field 设置为字符串。我在示例中将自定义类型命名为“mytype”。 (真实数据是嵌套的,我在输出中有更多字段设置为字符串 - 公共结构中的 id 字段只是一个测试)
我的意思是,它应该看起来像这样 - 还是不是?
func (m *mytype) MarshalJSON() ([]byte, error) {
...
}
这是我的示例代码:https://play.golang.org/p/rS9HddzDMp
package main
import (
"encoding/json"
"fmt"
"bytes"
)
/* ----------------------------------------------------------------------------------------------------
Definition of the internal Book object (read from input)
-----------------------------------------------------------------------------------------------------*/
type Book struct {
Id json.Number `json:"id"`
Revision int `json:"revision"`
ISBN json.Number `json:"isbn"`
Title string `json:"title"`
}
/* ----------------------------------------------------------------------------------------------------
Definition of the public Book object
-----------------------------------------------------------------------------------------------------*/
type AliasBook Book
type omit *struct{}
type mytype string
type PublicBook struct {
Id string `json:"id"`
Revision omit `json:"revision,omitempty"`
ISBN mytype `json:"isbn"`
*AliasBook
}
/* ----------------------------------------------------------------------------------------------------
Rendering functions
-----------------------------------------------------------------------------------------------------*/
func (bb *Book) MarshalJSON() ([]byte, error) {
fmt.Println("---------------MarschalJSON---------------")
aux := PublicBook{
Id: bb.Id.String(),
AliasBook: (*AliasBook)(bb),
}
return json.Marshal(&aux)
}
func main() {
var jsonStreams[2][]byte
// Input ISBN as string
jsonStreams[0] = []byte(`{"id":"123","revision":1234,"isbn":"978-3-86680-192-9","title":"Go for dummies"}`)
// Input ISBN as int
jsonStreams[1] = []byte(`{"id":123,"revision":1234,"isbn":9783866801929,"title":"Go for dummies"}`)
// For each stream
for i := range jsonStreams {
fmt.Print("stream: ")
fmt.Println(string(jsonStreams[i]))
// Read Input
b := Book{}
err := json.Unmarshal(jsonStreams[i], &b)
if err == nil {
fmt.Printf("%+v\n", b)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", b)
}
// Output as JSON
response := new(bytes.Buffer)
enc := json.NewEncoder(response)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
err = enc.Encode(&b)
if err == nil {
fmt.Printf("%+v\n", response)
} else {
fmt.Println(err)
fmt.Printf("%+v\n", response)
}
}
}
编辑 我有一个适合我的解决方案。 https://play.golang.org/p/Vr4eELsHs1
关键点是,我必须采用“fmt.Sprint(*isbn) 来返回封送器中的字符串。我创建了一个新类型,使用 json.Number 函数将输入转换为 int64 并使用json 自定义封送器到字符串。
【问题讨论】:
标签: json go interface marshalling