如何在Golang中正确序列化JSON字符串

1.Json.Marshal会有什么问题?

下边示例是将json序列化成bytes,然后把bytes反序列化到匹配的结构体。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
}

func main() {
	in := `{"firstName":"John","lastName":"Dow"}`

	bytes, err := json.Marshal(in)
	if err != nil {
		panic(err)
	}

	var p Person
	err = json.Unmarshal(bytes, &p)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v", p)
}

运行程序发现,程序panic了。

panic: json: cannot unmarshal string into Go value of type main.Person

goroutine 1 [running]:
main.main()
	/tmp/sandbox071126523/prog.go:24 +0x1e9

这不是我们想要的,接下来我们确认下json字符串是否跟Person结构体相匹配。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
}

func main() {
	bytes, err := json.Marshal(Person{
		FirstName: "John",
		LastName:  "Dow",
	})
	if err != nil {
		panic(err)
	}

	fmt.Println(string(bytes))
}

输出的结果如下:

{"firstName":"John","lastName":"Dow"}

序列化后的结构体,跟我们的json字符串是一样的。

2.原因是什么?

我们比较一下序列化json字符串以及结构体序列化的结果。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
}

func main() {
	bytes, err := json.Marshal(Person{
		FirstName: "John",
		LastName:  "Dow",
	})
	if err != nil {
		panic(err)
	}

	fmt.Println(string(bytes))

	in := `{"firstName":"John","lastName":"Dow"}`

	bytes, err = json.Marshal(in)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(bytes))
}

输出结果如下:

{"firstName":"John","lastName":"Dow"}
"{\"firstName\":\"John\",\"lastName\":\"Dow\"}"

你能看到转义的双引号么?这是问题的症结所在,json.Marshal在对字符串进行序列化的时候,会对字符串进行转义

3.如何避免被转义

json包对这个问题有一个解决方案,它有一个RawMessage类型,在序列化及反序列化时不会对字符串进行转义。
所以,如果你需要序列化一个json字符串,后续再反序列化到结构体里,可以用json.RawMessage来实现。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
}

func main() {
	in := `{"firstName":"John","lastName":"Dow"}`

	rawIn := json.RawMessage(in)
	bytes, err := rawIn.MarshalJSON()
	if err != nil {
		panic(err)
	}

	var p Person
	err = json.Unmarshal(bytes, &p)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v", p)
}

输出结果如下:

{FirstName:John LastName:Dow}

是正确的结果。

4.有没有更简单的方式

有的,json.RawMessage实际上是[]byte类型的,所以你需要做的就是把字符串转换成[]byte类型。

package main

import (
	"encoding/json"
	"fmt"
)

type Person struct {
	FirstName string `json:"firstName"`
	LastName  string `json:"lastName"`
}

func main() {
	in := `{"firstName":"John","lastName":"Dow"}`
	bytes := []byte(in)

	var p Person
	err := json.Unmarshal(bytes, &p)
	if err != nil {
		panic(err)
	}

	fmt.Printf("%+v", p)
}

输出结果是一样的:

{FirstName:John LastName:Dow}

参考:
How To Correctly Serialize JSON String In Golang

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值