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

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.如何避免被转义

RawMessagejson.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}