子兮子兮 子兮子兮

No can, but will.

目录
Golang 中 JSON 信息值的序列化和反序列化
/        

Golang 中 JSON 信息值的序列化和反序列化

要将已序列化的 JSON 字符串赋值给另一个 JSON 对象中的属性,需要先将 JSON 字符串反序列化。否则返回给客户端的 JSON 结果值可能会是一个包含转义符号 \ 的 JSON 字符串,如下所示:

{ "code": 1, data: "{ \"itanken.cn\": { \"remain\": 99945, \"success\": 11 }, \"com\": \"result2\", \"zixizixi.cn\": { \"remain\": 99780, \"success\": 44 } }", time: "2021-04-13 20:20:19.123" }

以上 JSON 数据的 data 属性被赋值成了一个存在转义字符字符串。造成这种问题的原因,就是因为在给 data 属性赋值前没有将 JSON 格式的字符串进行反序列化,或者将一个 JSON 格式的数据不小心进行了序列化。

在 Golang 中的 JSON 序列化表示将一个数据对象(如结构体、切片和 map 等)编码为字节数组(通过 string(jsonBytes) 转换为 JSON 格式的字符串,其中 jsonBytes 的数据类型为 []byte),JSON 反序列化表示将一个 JSON 格式的字节数组(通过 []byte(jsonStr) 将 JSON 格式字符串转换为 JSON 的字节数组)解码为对应的结构体、切片或 map 等类型的数据。

反序列化

因为我们想要的 data 属性应该是一个 JSON 对象,所以首先我们要知道的是,在给 data 赋值时,其值必须是一个未序列化的值(未序列化在此处可以理解为非字符串)。在 Golang 中,一个结构体、切片 和 map 等都是未序列化的值,序列化后的值通常为字节数组 []byte 或字符串。要将以上 JSON 数据的 data 赋值为一个 JSON,就要先进行反序列化,任何一个合法的 JSON 格式字符串,都可以反序列化为 map[string]interface{} 类型:

result := make(map[string]interface{})

jsonStr := "{ \"itanken.cn\": { \"remain\": 99945, \"success\": 11 }, \"com\": \"result2\", \"zixizixi.cn\": { \"remain\": 99780, \"success\": 44 } }"
value := new(map[string]interface{})
// 反序列化
err := json.Unmarshal([]byte(jsonStr), &value)
if err == nil {
	result["data"] = value
}

jsonStr 经过反序列化后再对 data 进行赋值,将 result 进行序列化得到的 JSON 字符串的 data 属性值将不再包含转义符号,因为其值由以前的 JSON 格式字符串变成了一个 JSON 对象。如果给 data 赋值前未将 jsonStr 进行反序列化,或者将 value 进行了序列化,再获取 result 的 JSON 字符串,相当于给 jsonStr 进行了两次序列化,第一次将序列化的 jsonStr 赋值给了 data,此时 data 的值是一个序列化的 JSON 格式字符串,然后将 result 进行序列化的时候 data 的值就发生了第二次序列化,从而包含了转义符号 /

序列化

比如要将 result 返回给客户端,就要经过序列化,将 result 编码为 JSON 格式的字节数组(客户端获取到编码后的字节数组后会进行反序列化得到 JSON 对象)。

// 模拟响应数据到客户端(序列化)
resultBytes, _ := json.Marshal(result)
fmt.Println("RESULT:\n", string(resultBytes))

完整示例代码

package main

import (
	"encoding/json"
	"fmt"
	"time"
)

func main() {
	jsonStr := `{ "itanken.cn": { "remain": 99945, "success": 11 }, "com": "result2", "zixizixi.cn": { "remain": 99780, "success": 44 } }`

	value := new(map[string]interface{})
	// 反序列化
	err := json.Unmarshal([]byte(jsonStr), &value)
	if err != nil {
		fmt.Println("JSON 字符串反序列化失败:", err.Error())
		return
	}
	fmt.Println("value:\n", value)
	// 序列化
	jsonBytes, _ := json.Marshal(value)
	fmt.Println("JSON:\n", string(jsonBytes))

	// 结果值
	result := make(map[string]interface{})
	result["code"] = 1
	result["data"] = value // data 必须是一个非序列化值,否则可能会进行二次转义
	result["time"] = time.Now().UnixNano()

	// 模拟响应数据到客户端(序列化)
	resultBytes, _ := json.Marshal(result)
	fmt.Println("RESULT:\n", string(resultBytes))
}