要将已序列化的 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))
}
内容声明 | |
---|---|
标题: Golang 中 JSON 信息值的序列化和反序列化 | |
链接: https://zixizixi.cn/golang-json-serializable | 来源: iTanken |
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可,转载请保留此声明。
|