go语言使用rejson模块存储的utf8中文读取时乱码
现象
使用json.Unmarshal将rejson读取的json转换成对象时中文乱码。
存储的对象1
2
3
4
5obj := map[string]interface{}{
"t1": "你好2Af1不行.a",
"t2": "你好",
}
读取到的json1
{"t1":"\u00e4\u00bd\u00a0\u00e5\u00a5\u00bd2Af1\u00e4\u00b8\u008d\u00e8\u00a1\u008c.a","t2":"\u00e4\u00bd\u00a0\u00e5\u00a5\u00bd"}
转成对象输出1
map[t1:ä½ å¥½2Af1ä¸è¡.a t2:ä½ å¥½]
查找问题
命令行查看,发现rejson读取到的内容和redis存储中一致。
命令行中写入中文,读取发现rejsond存储的中文会变成\u00xx格式
使用utf8格式文本存储文本,以十六进制方式读取。对比redis中的格式发现中文会转成\u00加二进制的方式存储。
解决
在使用json.Unmarshal之前先对\u00xx的文本进行替换。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
func Test() {
// 测试代码
rh := rejson.NewReJSONHandler()
client := redis.NewClient(&redis.Options{
Addr: "192.168.1.131:6379", // use default Addr
Password: "", // no password set
DB: 0, // use default DB
})
_, err := client.Ping().Result()
if err != nil {
return
}
rh.SetGoRedisClient(client)
key := "TEST"
path := "."
obj := map[string]interface{}{
"t1": "你好2Af1不行.a",
"t2": "你好",
}
fmt.Printf("%s\n", obj)
res, err := rh.JSONSet(key, path, obj)
if err != nil {
return
}
fmt.Println(res)
resJson, err := rh.JSONGet(key, path)
if err != nil {
return
}
fmt.Printf("%s\n", resJson)
obj2 := map[string]interface{}{}
err = json.Unmarshal(resJson.([]uint8), &obj2)
fmt.Printf("%s\n", obj2)
// 加上\u00xx转换为二进制
js2, err := RejsonDecodeu00xx(resJson.([]uint8))
if err != nil {
return
}
fmt.Printf("%s\n", js2)
obj3 := map[string]interface{}{}
err = json.Unmarshal(js2, &obj3)
if err != nil {
return
}
fmt.Printf("%s\n", obj3)
return
}
// TODO: magic func
// 解决rejson存utf8只管存储,不管取的问题
// rejson存储时遇到utf8格式的值,会直接以\u00加上十六进制字符串存储
// rejson.go模块读取时没有做相应的转换。
// 此时调用json.Unmarshal转换为对象时utf8文本会乱码
// 临时方案
func RejsonDecodeu00xx(str []byte) (res []byte, err error) {
l := len(str)
for i := 0; i < l; {
if '\\' == str[i] && i+6 <= l &&
'u' == str[i+1] && '0' == str[i+2] && '0' == str[i+3] {
//tmp := string(str[i])
a, o := unhex(str[i+4])
if !o {
err = errors.New("error !")
return []byte{}, err
}
b, o := unhex(str[i+5])
if !o {
err = errors.New("error !")
return []byte{}, err
}
c := a*16 + b
res = append(res, c)
i += 6
} else {
res = append(res, str[i])
i++
}
}
return res, err
}
func unhex(b uint8) (v uint8, ok bool) {
c := b
switch {
case '0' <= c && c <= '9':
return c - '0', true
case 'a' <= c && c <= 'f':
return c - 'a' + 10, true
case 'A' <= c && c <= 'F':
return c - 'A' + 10, true
}
return
}
输出: