go语言rejson读取后Unmarshal乱码的解决过程

 更新时间:2026年06月22日 10:26:27   作者:张拓1070410059  
探讨rejson中文乱码问题,解析JSON转对象过程中的编码问题,并提供解决方案,确保中文正确显示,使用json.Unmarshal前读取rejson存储的JSON数据时需注意特殊编码格式

现象

使用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
}

输出:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Go语言设计模式之结构型模式

    Go语言设计模式之结构型模式

    本文主要聚焦在结构型模式(Structural Pattern)上,其主要思想是将多个对象组装成较大的结构,并同时保持结构的灵活和高效,从程序的结构上解决模块之间的耦合问题
    2021-06-06
  • golang的协程上下文的具体使用

    golang的协程上下文的具体使用

    golang的context 主要用来在 goroutine 之间传递上下文信息,包括:取消信号、超时时间、截止时间、k-v 等,本文就详细的来介绍一下golang的协程上下文的具体使用,感兴趣的可以了解一下
    2022-04-04
  • Golang Compare And Swap算法详细介绍

    Golang Compare And Swap算法详细介绍

    CAS算法是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步Non-blocking Synchronization
    2022-10-10
  • go语言发送smtp邮件的实现示例

    go语言发送smtp邮件的实现示例

    这篇文章主要介绍了go发送smtp邮件的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • go操作Kafka使用示例详解

    go操作Kafka使用示例详解

    这篇文章主要为大家介绍了go操作Kafka使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • gomod包依赖管理工具使用详解

    gomod包依赖管理工具使用详解

    这篇文章主要为大家介绍了gomod如何解决包管理问题使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • gorm整合进go-zero的实现方法

    gorm整合进go-zero的实现方法

    go-zero提供的代码生成器里面,没有提供orm框架操作,但是提供了遍历的缓存操作,所以可以利用gorm当作一个sql语句的生成器,把生成后的sql语句放到go-zero生成的模板中去执行,对gorm整合进go-zero的实现方法感兴趣的朋友一起看看吧
    2022-03-03
  • Go语言使用漏桶算法和令牌桶算法来实现API限流

    Go语言使用漏桶算法和令牌桶算法来实现API限流

    为防止服务器被过多的请求压垮,限流是一个至关重要的技术手段,下面我们就来看看如何使用漏桶算法和令牌桶算法来实现 API 的限流吧
    2024-11-11
  • Golang实现Java虚拟机之解析class文件详解

    Golang实现Java虚拟机之解析class文件详解

    这篇文章主要为大家详细介绍了Golang实现Java虚拟机之解析class文件的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • go mod tidy命令的使用

    go mod tidy命令的使用

    gomodtidy命令是Go语言中用于管理项目依赖的工具,主要功能包括移除未使用的依赖项、添加缺失的依赖项以及更新go.sum文件以确保依赖项的正确校验,感兴趣的可以了解一下
    2024-11-11

最新评论