解析Json的两种方案
解析为Maps
元素使用前需要进行类型判断,number默认会转为float64,所以类型判断的时候必须用.(float64)判断
Go Type | JSON Type |
---|---|
bool | boolean |
float64 | number |
string | string |
nil pointer | null |
time.Time | RFC 3339 timestamp (string) |
package main
import (
"encoding/json"
"fmt"
)
func main() {
// Create a map to parse the JSON
var data map[string]interface{}
// Define a JSON string
j := `{"name":"example","numbers":[1,2,3,4],"nested":{"isit":true,"description":"a nested json"}}`
// Parse our JSON string
err := json.Unmarshal([]byte(j), &data)
if err != nil {
fmt.Printf("Error parsing JSON string - %s", err)
}
// Print out one of our JSON values
fmt.Printf("Name is %s, Numbers[0] is %f", data["name"].(string), data["numbers"].([]interface{})[0].(float64))
}
输出:
map[name:example nested:map[description:a nested json isit:true] numbers:[1 2 3 4]]
Name is example, Numbers[0] is 1.000000
Program exited.
解析为Struct
package main
import (
"encoding/json"
"fmt"
)
// Example is our main data structure used for JSON parsing
type Example struct {
Name string `json:"name"`
Numbers []int `json:"numbers"`
Nested Nested `json:"nested"`
}
// Nested is an embedded structure within Example
type Nested struct {
IsIt bool `json:"isit"`
Description string `json:"description"`
}
func main() {
// Define a JSON string
j := `{"name":"example","numbers":[1,2,3,4],"nested":{"isit":true,"description":"a nested json"}}`
// Parse JSON string into data object
var data Example
err := json.Unmarshal([]byte(j), &data)
if err != nil {
fmt.Printf("Error parsing JSON string - %s", err)
}
// Print the name
fmt.Printf("Name is %s", data.Name)
}
匿名结构体
package main
import (
"fmt"
"encoding/json"
)
type Config struct {
Server struct {
Host string `json:"host"`
Port string `json:"port"`
} `json:"server"`
Postgres struct {
Host string `json:"host"`
User string `json:"user"`
Password string `json:"password"`
DB string `json:"db"`
} `json:"database"`
}
func main() {
jsonConfig := []byte(`{
"server":{
"host":"localhost",
"port":"8080"},
"database":{
"host":"localhost",
"user":"db_user",
"password":"supersecret",
"db":"my_db"}}`)
var config Config
err := json.Unmarshal(jsonConfig, &config)
if err != nil {
panic(err)
}
fmt.Printf("Config: %+v\n", config)
}
输出:
Config: {Server:{Host:localhost Port:8080} Postgres:{Host:localhost User:db_user Password:supersecret DB:my_db}}
Program exited.
Unexported Filed
struct to json
Struct转成json的时候,会自动忽略unexported(首字母小写)的字段,比如下图中的weight,如果想被解析为json,则需要将weight的首字母大写。
package main
import (
"encoding/json"
"fmt"
"time"
)
type PersonAllowEmpty struct {
Name string
Age int64
Birth time.Time
weight string //The encoding/json package and similar packages ignore unexported fields.
}
func main() {
person := PersonAllowEmpty{}
jsonBytes, _ := json.Marshal(person)
fmt.Println(string(jsonBytes))
}
输出:
{"Name":"","Age":0,"Birth":"0001-01-01T00:00:00Z"}
Program exited.
空字段问题
struct to json
package main
import (
"encoding/json"
"fmt"
"time"
)
type Person struct {
Name string
Age int64
Birth time.Time
Children []Person
}
func main() {
person := Person{}
jsonBytes, _ := json.Marshal(person)
fmt.Println(string(jsonBytes))
}
输出:
{"Name":"","Age":0,"Birth":"0001-01-01T00:00:00Z","Children":null}
Program exited.
当 struct 中的字段没有值时,使用 json.Marshal 方法并不会自动忽略这些字段,而是根据字段的类型输出了他们的默认空值,这往往和我们的预期不一致,json 包提供了对字段的控制手段,我们可以为字段增加 omitempty tag,这个 tag 会在字段值为零值(int 和 float 类型零值是 0,string 类型零值是 "",对象类型零值是 nil)时,忽略该字段。
struct to json带上标签
package main
import (
"encoding/json"
"fmt"
"time"
)
type PersonAllowEmpty struct {
Name string `json:",omitempty"`
Age int64 `json:",omitempty"`
Birth time.Time `json:",omitempty"`
Children []PersonAllowEmpty `json:",omitempty"`
unexport string
}
func main() {
person := PersonAllowEmpty{}
jsonBytes, _ := json.Marshal(person)
fmt.Println(string(jsonBytes))
}
输出:
{"Birth":"0001-01-01T00:00:00Z"}
Program exited.
可以看到,这次输出的 json 中只有 Birth 字段了,string、int、对象类型的字段,都因为没有赋值,默认是零值,所以被忽略,对于日期时间类型,由于不可以设置为零值,也就是 0000-00-00 00:00:00,不会被忽略。
struct to json永久忽略字段
如果想要某一个字段在任何情况下都被 json 包忽略,需要使用如下的写法。
package main
import (
"encoding/json"
"fmt"
"time"
)
type Person struct {
Name string `json:"-"`
Age int64 `json:"-"`
Birth time.Time `json:"-"`
Children []string `json:"-"`
}
func main() {
birth, _ := time.Parse(time.RFC3339, "1988-12-02T15:04:27+08:00")
person := Person{
Name: "Wang Wu",
Age: 30,
Birth: birth,
Children: []string{},
}
jsonBytes, _ := json.Marshal(person)
fmt.Println(string(jsonBytes))
}
输出:
{}
Program exited.
json to struct 字段不全时会使用默认值
package main
import (
"encoding/json"
"fmt"
"time"
)
type Person struct {
Name string
Age int64
Birth time.Time
Children []Person
}
func main() {
var person Person
data := []byte(`{"Name": "1"}`)
err := json. Unmarshal(data, &person)
fmt.Println(person, err)
}
输出
{1 0 0001-01-01 00:00:00 +0000 UTC []} <nil>
Program exited.
json to struct 字段值为null也会使用默认值
package main
import (
"encoding/json"
"fmt"
"time"
)
type Person struct {
Name string
Age int64
Birth time.Time
Children []Person
}
func main() {
var person Person
data := []byte(`{"Name": null}`)
err := json. Unmarshal(data, &person)
fmt.Println(person, err)
}
输出:
{ 0 0001-01-01 00:00:00 +0000 UTC []} <nil>
Program exited.
字段不匹配
json中字段多
package main
import "fmt"
import "encoding/json"
type AutoGenerated struct {
Aa int `json:"aa"`
B int `json:"b"`
}
func main() {
c := "{\"aa\": 1, \"b\":2, \"c\":3}"
var a AutoGenerated
json.Unmarshal([]byte(c), &a)
fmt.Println(a)
}
输出:
{1 2}
Program exited.
解析嵌套interface
有时候返回的结果可能有多种,这个时候就可能把结构体的字段定义为interface,如
// YiqiuResponse defined yiqiu basic response
type YiqiuResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Code int `json:"code"`
Data interface{} `json:"data"`
}
如何继续把interface解析为struct
第一种
//https://stackoverflow.com/questions/43325288/golang-convert-interface-to-struct/43325450
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedDTO := UniversalDTO{}
json.Unmarshal(byteData, &receivedDTO)
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedDTO.Data)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
customer := Customer{}
bodyBytes, _ := json.Marshal(data)
json.Unmarshal(bodyBytes, &customer)
return customer
}
第二种,better
type Customer struct {
Name string `json:"name"`
}
type UniversalDTO struct {
Data interface{} `json:"data"`
// more fields with important meta-data about the message...
}
func main() {
// create a customer, add it to DTO object and marshal it
customer := Customer{Name: "Ben"}
dtoToSend := UniversalDTO{customer}
byteData, _ := json.Marshal(dtoToSend)
// unmarshal it (usually after receiving bytes from somewhere)
receivedCustomer := &Customer{}
receivedDTO := UniversalDTO{Data: receivedCustomer}
json.Unmarshal(byteData, &receivedDTO)
//done
fmt.Println(receivedCustomer)
}
结构体方法自我解析函数
https://zhuanlan.zhihu.com/p/116638548
null in json
The following case will be encoded as null:
- Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
- Pointer values encode as the value pointed to. A nil pointer encodes as the null JSON value.
- Interface values encode as the value contained in the interface. A nil interface value encodes as the null JSON value.
- The JSON null value unmarshals into an interface, map, pointer, or slice by setting that Go value to nil. Because null is often used in JSON to mean “not present,” unmarshaling a JSON null into any other Go type has no effect on the value and produces no error.
array and slice
Marshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x []int
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = make([]int, 0, 0)
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
输出:
true
null
false
[]
Unmarshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x []int
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`[123,456]`)
var xx []int
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
输出:
true
true
[]
true
false
[123 456]
pointer
Marshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x *int
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
num := 110
x = &num
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
输出:
true
null
false
110
Unmarshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x *int
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`123`)
var xx *int
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx, *xx)
}
输出:
true
true
<nil>
true
false
0xc0000140a8 123
interface
Marshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x interface{}
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = 110
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
输出:
true
null
false
119
Unmarshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x interface{}
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`123`)
var xx interface{}
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
输出:
true
true
<nil>
true
false
123
map
Marshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
var x map[string]string
xJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xJSON))
x = make(map[string]string)
xxJSON, err := json.Marshal(x)
if err != nil {
fmt.Println("failed to marshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(string(xxJSON))
}
输出:
true
null
false
{}
Unmarshal
package main
import (
"encoding/json"
"fmt"
)
func main() {
bs := []byte(`null`)
var x map[string]string
fmt.Println(x == nil)
if err := json.Unmarshal(bs, &x); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(x == nil)
fmt.Println(x)
bs = []byte(`{"abc":"123"}`)
var xx map[string]string
fmt.Println(xx == nil)
if err := json.Unmarshal(bs, &xx); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println(xx == nil)
fmt.Println(xx)
}
输出:
true
true
map[]
true
false
map[abc:123]
结构体
- null 是个特殊字符串,经过 json.Unmarshal 处理后,返回的 err 为 nil
- p1 定义为 person 本身,null 解析后,person 所有成员字段均为 golang 默认值
- p2 定义为 person 指针,null 解析后,p2 为 nil 指针
package main
import (
"encoding/json"
"fmt"
)
type person struct {
name string
age int
friends []string
phone *string
}
func main() {
pJSON := []byte("null")
var p1 person
if err := json.Unmarshal(pJSON, &p1); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println("p1", p1, p1.phone == nil, p1.friends == nil)
var p2 *person = nil
if err := json.Unmarshal(pJSON, &p2); err != nil {
fmt.Println("failed to unmarshal, err:", err.Error())
return
}
fmt.Println("p2", p2 == nil, p2)
}
输出:
p1 { 0 [] <nil>} true true
p2 true <nil>
结构体指针
结构体以及结构体指针转成json效果是一样的。
struct to json
package main
import (
"encoding/json"
"fmt"
)
type test struct {
A string
B int
}
func main() {
ts1 := make([]test, 2)
tps1 := make([]*test, 2)
for idx := 0; idx < 2; idx++ {
ts1[idx].A = "a"
ts1[idx].B = 1
tps1[idx] = &test{
A: "a",
B: 1,
}
}
ts1byte, _ := json.Marshal(ts1[0])
tps1byte, _ := json.Marshal(tps1[0])
fmt.Println(string(ts1byte))
fmt.Println(string(tps1byte))
}
输出:
{"A":"a","B":1}
{"A":"a","B":1}
结构体数组和结构体指针数组也一样
package main
import (
"encoding/json"
"fmt"
)
type test struct {
A string
B int
}
func main() {
ts1 := make([]test, 2)
tps1 := make([]*test, 2)
for idx := 0; idx < 2; idx++ {
ts1[idx].A = "a"
ts1[idx].B = 1
tps1[idx] = &test{
A: "a",
B: 1,
}
}
ts1byte, _ := json.Marshal(ts1)
tps1byte, _ := json.Marshal(tps1)
fmt.Println(string(ts1byte))
fmt.Println(string(tps1byte))
}
输出:
[{"A":"a","B":1},{"A":"a","B":1}]
[{"A":"a","B":1},{"A":"a","B":1}]
使用interface传递结构体
参考encoding/json
package main
import (
"encoding/json"
"fmt"
)
// Example is our main data structure used for JSON parsing
type Example struct {
Name string `json:"name"`
Numbers []int `json:"numbers"`
Nested Nested `json:"nested"`
}
type Example1 struct {
Name string `json:"name"`
Numbers []int `json:"numbers"`
}
// Nested is an embedded structure within Example*
type Nested struct {
IsIt bool `json:"isit"`
Description string `json:"description"`
}
func test(s string, i interface{}) {
err := json.Unmarshal([]byte(s), &i)
if err != nil {
fmt.Printf("Error parsing JSON string - %s", err)
}
// Print the name
fmt.Printf("Name is %v\n", i)
}
func main() {
// Define a JSON string
j := `{"name":"example","numbers":[1,2,3,4],"nested":{"isit":true,"description":"a nested json"}}`
// Parse JSON string into data object
data := &Example{}
test(j, data)
fmt.Printf("Name is %s\n", data.Name)
data1 := &Example1{}
test(j, data1)
fmt.Printf("Name is %s\n", data.Name)
}
输出:
Name is &{example [1 2 3 4] {true a nested json}}
Name is example
Name is &{example [1 2 3 4]}
Name is example