golang JSON数据编码与解码

JSON编码常用函数

  • func NewEncoder(w io.Writer) Encoder
    NewEncoder创建一个将数据写入w的
    Encoder。

  • func (enc *Encoder) Encode(v interface{}) error
    Encode将v的json编码写入输出流,并会写入一个换行符

  • func Marshal(v interface{}) ([]byte, error)
    Marshal函数返回v的json编码。

  • func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
    MarshalIndent类似Marshal但会使用缩进将输出格式化。

  • func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
    Indent函数将json编码的调整缩进之后写入dst。每一个json元素/数组都另起一行开始,以prefix为起始,一或多个indent缩进(数目看嵌套层数)。写入dst的数据起始没有prefix字符,也没有indent字符,最后也不换行,因此可以更好的嵌入其他格式化后的json数据里

示例:

// parse_json.go
package main

import (
	// "bytes"
	"encoding/json"
	"fmt"
	"os"
)

type user struct {
	Name string
	Age  int
	Sex  bool
}

func main() {

	var user_map = map[int]user{1: {"zhangsan", 20, true}, 2: {"lisi", 20, false}}
	// 编码JSON数据并返回
	bt_data, _ := json.Marshal(user_map)
	fmt.Println(string(bt_data))

	// 编码JSON数据并以缩进方式返回
	indent_bt_data, _ := json.MarshalIndent(user_map, "", "  ")
	fmt.Println("indent_bt_data = ", string(indent_bt_data))

	// 将编码完的JSON数据直接写入到文件中
	json_w_fd, _ := os.OpenFile("./out.json", os.O_CREATE, 0666)

	json_encoder := json.NewEncoder(json_w_fd)
	json_encoder.Encode(user_map)
	json_w_fd.Close()

	// 将编码完的JSON数据合并到其他数据中
	// dst := bytes.NewBuffer(indent_bt_data)
	// json.Indent(dst, bt_data, "", "")
	// fmt.Println(dst.String())

}

运行结果:

golang JSON数据编码与解码_第1张图片

JSON解码常用函数

  • func NewDecoder(r io.Reader) Decoder
    NewDecoder创建一个从r读取并解码json对象的
    Decoder,解码器有自己的缓冲,并可能超前读取部分json数据

  • func (dec *Decoder) Decode(v interface{}) error
    Decode从输入流读取下一个json编码值并保存在v指向的值里,参见Unmarshal函数的文档获取细节信息。

  • func Unmarshal(data []byte, v interface{}) error
    Unmarshal函数解析json编码的数据并将结果存入v指向的值。

Unmarshal和Marshal做相反的操作,必要时申请映射、切片或指针,有如下的附加规则:

要将json数据解码写入一个指针,Unmarshal函数首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。

要将json数据解码写入一个结构体,函数会匹配输入对象的键和Marshal使用的键(结构体字段名或者它的标签指定的键名),优先选择精确的匹配,但也接受大小写不敏感的匹配。

要将json数据解码写入一个接口类型值,函数会将数据解码为如下类型写入接口:

Bool 对应JSON布尔类型
float64 对应JSON数字类型
string 对应JSON字符串类型
[]interface{} 对应JSON数组
map[string]interface{} 对应JSON对象
nil 对应JSON的null
如果一个JSON值不匹配给出的目标类型,或者如果一个json数字写入目标类型时溢出,Unmarshal函数会跳过该字段并尽量完成其余的解码操作。如果没有出现更加严重的错误,本函数会返回一个描述第一个此类错误的详细信息的UnmarshalTypeError。

JSON的null值解码为go的接口、指针、切片时会将它们设为nil,因为null在json里一般表示“不存在”。 解码json的null值到其他go类型时,不会造成任何改变,也不会产生错误。

当解码字符串时,不合法的utf-8或utf-16代理(字符)对不视为错误,而是将非法字符替换为unicode字符U+FFFD。

代码

// json_decode.go
package main

import (
	// "bytes"
	"encoding/json"
	"fmt"
	"os"
)

type user struct {
	Name string
	Age  int
	Sex  bool
}

func main() {
	var user_map map[int]user
	// bt_data []byte

	json_rd_fd, _ := os.Open("./out.json")

	json_decode := json.NewDecoder(json_rd_fd)
	json_decode.Decode(&user_map)
	
	fmt.Println(user_map)
	json_rd_fd.Close()

	json_str := "{\"1\":{\"Name\":\"wangwu\",\"Age\":18,\"Sex\":true},\"2\":{\"Name\":\"chenliu\",\"Age\":29,\"Sex\":false}}"
	json.Unmarshal([]byte(json_str), &user_map)
	
	fmt.Println(user_map)

}

运行结果:

golang JSON数据编码与解码_第2张图片

下面是RawMessage类型的JSON处理方法:

  • type RawMessage []byte

RawMessage类型是一个保持原本编码的json对象。本类型实现了Marshaler和Unmarshaler接口,用于延迟json的解码或者预计算json的编码。
即在第一次解码时,RawMessage类型的数据先保留JSON格式。

如下代码来自golang标准文档库

type Color struct {
    Space string
    Point json.RawMessage // delay parsing until we know the color space
}
type RGB struct {
    R   uint8
    G   uint8
    B   uint8
}
type YCbCr struct {
    Y   uint8
    Cb  int8
    Cr  int8
}
var j = []byte(`[
		{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
		{"Space": "RGB",   "Point": {"R": 98, "G": 218, "B": 255}}
	]`)
var colors []Color
err := json.Unmarshal(j, &colors)
if err != nil {
    log.Fatalln("error:", err)
}
for _, c := range colors {
    var dst interface{}
    switch c.Space {
    case "RGB":
        dst = new(RGB)
    case "YCbCr":
        dst = new(YCbCr)
    }
    err := json.Unmarshal(c.Point, dst)
    if err != nil {
        log.Fatalln("error:", err)
    }
    fmt.Println(c.Space, dst)
}

结果:

YCbCr &{255 0 -10}
RGB &{98 218 255}

你可能感兴趣的:(golang)