go语言rejson读取后Unmarshal乱码

go语言使用rejson模块存储的utf8中文读取时乱码

现象

使用json.Unmarshal将rejson读取的json转换成对象时中文乱码。
存储的对象

	obj := map[string]interface{}{
		"t1": "你好2Af1不行.a",
		"t2": "你好",
	}
	

读取到的json

{"t1":"\u00e4\u00bd\u00a0\u00e5\u00a5\u00bd2Af1\u00e4\u00b8\u008d\u00e8\u00a1\u008c.a","t2":"\u00e4\u00bd\u00a0\u00e5\u00a5\u00bd"}

转成对象输出

map[t1:ä½ å¥½2Af1不行.a t2:ä½ å¥½]

在这里插入图片描述

查找问题

命令行查看,发现rejson读取到的内容和redis存储中一致。
在这里插入图片描述
命令行中写入中文,读取发现rejsond存储的中文会变成\u00xx格式
在这里插入图片描述
使用utf8格式文本存储文本,以十六进制方式读取。对比redis中的格式发现中文会转成\u00加二进制的方式存储。
在这里插入图片描述

解决

在使用json.Unmarshal之前先对\u00xx的文本进行替换。


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
}

输出:
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言中,判断结构体是否为空可以通过判断结构体的各个字段是否为空来实现。对于使用`json.Unmarshal`解析后的结构体,你可以通过判断其中的字段是否为其零值来确定结构体是否为空。以下是一个示例代码: ```go package main import ( "encoding/json" "fmt" ) type Person struct { Name string `json:"name"` Age int `json:"age"` Email string `json:"email"` } func IsEmptyStruct(s interface{}) bool { // 将结构体转换为JSON字符串 jsonStr, _ := json.Marshal(s) // 判断JSON字符串是否为空 return string(jsonStr) == "{}" } func main() { // 示例1:空结构体 var p1 Person fmt.Println("Is p1 empty?", IsEmptyStruct(p1)) // 示例2:非空结构体 p2 := Person{Name: "Alice", Age: 30, Email: "alice@example.com"} fmt.Println("Is p2 empty?", IsEmptyStruct(p2)) } ``` 在上述代码中,我们定义了一个`Person`结构体,并实现了一个`IsEmptyStruct`函数来判断结构体是否为空。函数内部先将结构体转换为JSON字符串,然后判断该JSON字符串是否为空。如果JSON字符串为空字符串`{}`,则说明结构体为空;否则,结构体不为空。 在示例中,我们分别创建了一个空结构体`p1`和一个非空结构体`p2`,并通过调用`IsEmptyStruct`函数来判断它们是否为空。 请注意,这种方法只能判断结构体中的字段是否为空,不能判断结构体中的嵌套结构体是否为空。如果需要判断嵌套结构体的空值,可以递归地对嵌套结构体进行判断。同时,结构体的零值和空值的定义可能因字段类型的不同而不同,需要根据实际情况进行判断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值