golang json


golang关于json库的一个比较容易陷入的坑 uint8[]数组的json转换问题.

 

类似这个CA如果实例转化成json.List会变成字符串.

type CA struct {
List []uint8
}

func main() {
ca := CA{[]uint8{1,2,3,4,5,6,7,8,9,0}}
r, _ := json.Marshal(ca)
fmt.Println(string(r)) //{"List":"AQIDBAUGBwgJAA=="}
}

而我们希望的是要一个正常的json. 只有 int8 byte uint8 这种8位的json库会给我们当成字符串处理.想要解决.如果拍脑袋就不能用这几种类型了.需要使用16 32 64位的数字才可以正常转换成json字符串.

{"List":[1,2,3,4,5,6,7,8,9,0]}


但是不用担心. Unmarshal这个 我们认为不想要的json字符串 重新到CA的其他实例 会得到想要的结果.

.如果是跨语言的json通信就要小心了.
————————————————
原文链接:https://blog.csdn.net/spiritring/article/details/11570219

对于不知道类型的多源数据流的解码通常这样:

采用标准的encoding/json库将数据解码为通用map[string]interface{}类型
利用mapstructure库转为相应的 Go 结构体

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "github.com/mitchellh/mapstructure"
)

type Person struct {
    Name string
    Age  int
    Job  string
}

type Cat struct {
    Name  string
    Age   int
    Breed string
}
func (c *Cat) miao(){
    fmt.Println("喵喵喵~")
}

func main() {
    datas := []string{
        `{
          "type": "person",
          "name":"dj",
          "age":18,
          "job": "programmer"
        }`,
        `{
          "type": "cat",
          "name": "kitty",
          "age": 1,
          "breed": "Ragdoll"
        }`,
    }

    for _, data := range datas {
        var m map[string]interface{}
        err := json.Unmarshal([]byte(data), &m)  //转到通用接口中
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println(m["type"])  
        //输出 person
        fmt.Println(m)
        //输出 map[age:18 job:programmer name:dj type:person]
        switch m["type"].(string) {   //获取key-value,接口类型转为字符出(断言)
        case "person":
            var p Person
            mapstructure.Decode(m, &p)  //转为结构体
            fmt.Println("person", p)
            //输出 person {dj 18 programmer}
        case "cat":
            var cat Cat
            mapstructure.Decode(m, &cat)
            fmt.Println("cat", cat)
            cat.miao()
        }
    }
}
map1 := make(map[string]interface{})
    map1["1"] = "hello"
    map1["2"] = "world"
    //return []byte
    str, err := json.Marshal(map1)

    if err != nil {
        fmt.Println(err)
    }
    fmt.Println("map to json", string(str))

    //json([]byte) to map
    map2 := make(map[string]interface{})
    err = json.Unmarshal(str, &map2)
    if err != nil {
        fmt.Println(err)
    }

https://blog.csdn.net/wowenlong/article/details/113571853

 https://blog.csdn.net/xz_studying/article/details/109278619

Go按照RFC 4627的标准实现了一个json编解码的标准库

func Unmarshal(data []byte, v interface{}) error
Unmarshal用于反序列化json的函数 根据data将数据反序列化到传入的对象中
仔细查看代码中的四种情况

1 将json反序列化成struct对象

2 将json反序列化到可以存储struct的slice中

3 将json 反序列化到map中

4 将json反序列化到slice中


package main

import (
"encoding/json"
"fmt"
)

func main() {
type Person struct {
Name string
Age int
Gender bool
}
//unmarshal to struct
var p Person
var str = `{"Name":"junbin", "Age":21, "Gender":true}`
json.Unmarshal([]byte(str), &p)
//result --> junbin : 21 : true
fmt.Println(p.Name, ":", p.Age, ":", p.Gender)

// unmarshal to slice-struct
var ps []Person
var aJson = `[{"Name":"junbin", "Age":21, "Gender":true},
{"Name":"junbin", "Age":21, "Gender":true}]`
json.Unmarshal([]byte(aJson), &ps)
//result --> [{junbin 21 true} {junbin 21 true}] len is 2
fmt.Println(ps, "len is", len(ps))

// unmarshal to map[string]interface{}
var obj interface{} // var obj map[string]interface{}
json.Unmarshal([]byte(str), &obj)
m := obj.(map[string]interface{})
//result --> junbin : 21 : true
fmt.Println(m["Name"], ":", m["Age"], ":", m["Gender"])

//unmarshal to slice
var strs string = `["Go", "Java", "C", "Php"]`
var aStr []string
json.Unmarshal([]byte(strs), &aStr)
//result --> [Go Java C Php] len is 4
fmt.Println(aStr, " len is", len(aStr))
}


func Marshal(v interface{}) ([]byte, error)
Marshal 用于将struct对象序列化到json对象中
下面这个例子讲解了以下几个例子

1 给field指定别名

2 序列化时忽略字段

3 序列化时忽略值为zero value的字段

4 序列化时 将int类型的值 转换成string

5 slice序列化为json

6 map序列化为json


package main

import (
"encoding/json"
"fmt"
)

//tag中的第一个参数是用来指定别名
//比如Name 指定别名为 username `json:"username"`
//如果不想指定别名但是想指定其他参数用逗号来分隔
//omitempty 指定到一个field时
//如果在赋值时对该属性赋值 或者 对该属性赋值为 zero value
//那么将Person序列化成json时会忽略该字段
//- 指定到一个field时
//无论有没有值将Person序列化成json时都会忽略该字段
//string 指定到一个field时
//比如Person中的Count为int类型 如果没有任何指定在序列化
//到json之后也是int 比如这个样子 "Count":0
//但是如果指定了string之后序列化之后也是string类型的
//那么就是这个样子"Count":"0"
type Person struct {
Name string `json:"username"`
Age int
Gender bool `json:",omitempty"`
Profile string
OmitContent string `json:"-"`
Count int `json:",string"`
}

func main() {
var p *Person = &Person{
Name: "brainwu",
Age: 21,
Gender: true,
Profile: "I am Wujunbin",
OmitContent: "OmitConent",
}
if bs, err := json.Marshal(&p); err != nil {
panic(err)
} else {
//result --> {"username":"brainwu","Age":21,"Gender":true,"Profile":"I am Wujunbin","Count":"0"}
fmt.Println(string(bs))
}

var p2 *Person = &Person{
Name: "brainwu",
Age: 21,
Profile: "I am Wujunbin",
OmitContent: "OmitConent",
}
if bs, err := json.Marshal(&p2); err != nil {
panic(err)
} else {
//result --> {"username":"brainwu","Age":21,"Profile":"I am Wujunbin","Count":"0"}
fmt.Println(string(bs))
}

// slice 序列化为json
var aStr []string = []string{"Go", "Java", "Python", "Android"}
if bs, err := json.Marshal(aStr); err != nil {
panic(err)
} else {
//result --> ["Go","Java","Python","Android"]
fmt.Println(string(bs))
}

//map 序列化为json
var m map[string]string = make(map[string]string)
m["Go"] = "No.1"
m["Java"] = "No.2"
m["C"] = "No.3"
if bs, err := json.Marshal(m); err != nil {
panic(err)
} else {
//result --> {"C":"No.3","Go":"No.1","Java":"No.2"}
fmt.Println(string(bs))
}
}
————————————————
版权声明:本文为CSDN博主「Iconoclast_wu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012807459/article/details/38962439

https://www.cnblogs.com/haiguixiansheng/articles/10718531.html

在实际项目中,编码成json串的数据结构,往往是切片类型。如下定义了一个[]StuRead类型的切片  
package main
 
import (
   "encoding/json"
   "fmt"
)
 
func main() {
   type StuRead struct {
      Name  interface{} `json:"name"`
      Age   interface{}
      HIgh  interface{}
      sex   interface{}
      Class interface{} `json:"class"`
      Test  interface{}
   }
 
 
   //方式1:只声明,不分配内存
   var stus1 []*StuRead
 
   //方式2:分配初始值为0的内存
   stus2 := make([]*StuRead,0)
 
   //错误示范
   //new()只能实例化一个struct对象,而[]StuRead是切片,不是对象
   stus := new([]StuRead)
 
   stu1 := &StuRead{"asd1",1,1,1,1,1}
   stu2 := &StuRead{"asd2",2,2,2,2,2}
 
   //由方式1和2创建的切片,都能成功追加数据
   //方式2最好分配0长度,append时会自动增长。反之指定初始长度,长度不够时不会自动增长,导致数据丢失
   stus1 = append(stus1,stu1)  //因为上面stus1是切片类型的结构体指针类型,所以append的类型也必须是取的地址。
   stus2 = append(stus2,stu2)  //因为上面stus2是切片类型的结构体指针类型,所以append的类型也必须是取的地址。
 
   //成功编码
   json1,_ := json.Marshal(stus1)
   json2,_ := json.Marshal(stus2)
   fmt.Println(string(json1))
   fmt.Println(string(json2))
}
//打印效果
[{"name":"asd1","Age":1,"HIgh":1,"class":1,"Test":1}]
[{"name":"asd2","Age":2,"HIgh":2,"class":2,"Test":2}]

嵌套数据结构

https://blog.csdn.net/zhengzizhi/article/details/74078620