如何正确地将带有String()方法的嵌入式结构序列化为JSON字符串?
此代码输出:如何正确地将带有String()方法的嵌入式结构序列化为JSON字符串?,json,string,go,serialization,format,Json,String,Go,Serialization,Format,此代码输出: package main import ( "fmt" "encoding/json" ) type Ticket struct { From string To string } func (t Ticket) String() string { return fmt.Sprintf("%s - %s", t.From, t.To) } type Passenger struct { Name string `j
package main
import (
"fmt"
"encoding/json"
)
type Ticket struct {
From string
To string
}
func (t Ticket) String() string {
return fmt.Sprintf("%s - %s", t.From, t.To)
}
type Passenger struct {
Name string `json:"Name"`
Tkt Ticket `json:"Ticket"`
}
func main() {
p := Passenger{}
p.Name = "John"
p.Tkt.From = "New York"
p.Tkt.To = "Washington"
buf, _ := json.Marshal(p)
fmt.Println(string(buf))
}
但是,使用json.Marshal()
method(对于复杂结构来说,这既简单又友好),如何使其输出如下:
{"Name":"John","Ticket":{"From":"New York","To":"Washington"}}
func (t Ticket) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
为了生成Go值的JSON表示,包将检查该值是否实现了或接口,如果实现了,则使用/调用它们(按此顺序)。该文件记录在: 封送处理递归地遍历值v。如果遇到的值实现了Marshaler接口,并且不是nil指针,Marshall将调用其MarshalJSON方法来生成JSON。如果不存在MarshalJSON方法,但该值实现encoding.TextMarshaler,则Marshal将调用其MarshalText方法并将结果编码为JSON字符串
json/encoding
包不关心String()
方法。因此,如果您想控制值的JSON表示/输出(Ticket
struct),请在其上实现JSON.Marshaler
(您可以根据自己的喜好调用String()
):
然后输出将如您所愿:
func (t Ticket) MarshalJSON() ([]byte, error) {
return []byte(`"` + t.String() + `"`), nil
}
试穿一下
需要注意一件事:如果Ticket.string()
生成的字符串包含引号“
,则输出将成为无效的JSON,或者更可能的是JSON.Marshal()
将返回错误
要处理这种转义,最好/最简单的方法是使用json
包本身:告诉它对Ticket.string()的string
结果进行json编码:
{"Name":"John","Ticket":"New York - Washington"}
现在,如果我们这样测试它:
{"Name":"John","Ticket":{"From":"New York","To":"Washington"}}
func (t Ticket) MarshalJSON() ([]byte, error) {
return json.Marshal(t.String())
}
输出仍将是有效的JSON(请在上尝试):
{“姓名”:“约翰”,“票证”:“纽约\“纽约-华盛顿”}
绝妙的解决方案。谢谢。顺便说一下,您可以使用%q
而不是%s
,它会为您引用字符串@Kaedys你让我意识到我忘了输入中的潜在引号。我更新了这个问题,建议使用json
包本身来处理这些问题。这个调用很好,不过%q
标记到fmt.Sprintf()
也会自动转义输入字符串中的任何引号。@Kaedys是的,在这种情况下这两个都可以工作。但一般来说,最好将转义留给将处理所有情况的json
包。
{"Name":"John","Ticket":"New\" York - Washington"} <nil>