脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|shell|

服务器之家 - 脚本之家 - Golang - Go json反序列化“null“的问题解决

Go json反序列化“null“的问题解决

2023-03-15 16:27NJU_lemon Golang

本文主要介绍了Go json反序列化“null“的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

有这么一段代码,可以先看一下有没有什么问题,作用是输入一段json字符串,反序列化成map,然后将另一个inputMap的内容,merge进这个map

  1. func mergeContent(inputJson string, inputMap map[string]interface{}) (map[string]interface{}, error) {
  2. jsonMap := make(map[string]interface{})
  3. if inputJson != "" {
  4. decoder := jsoniter.NewDecoder(strings.NewReader(inputJson))
  5. decoder.UseNumber()
  6. if err := decoder.Decode(&jsonMap); err != nil {
  7. return nil, err
  8. }
  9. }
  10. //merge
  11. for k, v := range inputMap {
  12. jsonMap[k] = v
  13. }
  14. return jsonMap, nil
  15. }

看上去是不是一段很健康的代码? 结合标题再看看呢? 如果输入的json字符串是"null"会发生什么呢?

实验

  1. func main(){
  2. inputMap := make(map[string]interface{})
  3. inputMap["test"] = 1
  4. outputMap, err := mergeContent("null", inputMap)
  5. if err != nil {
  6. fmt.Println("err:", err)
  7. return
  8. }
  9. fmt.Printf("output:%+v\n", outputMap)
  10. }

不出意外的话,要出意外了

Go json反序列化“null“的问题解决

它说我给一个nil map赋值了,但我明明在反序列化之前给jsonMap初始化了的,原来,jsoniter这个库【其他库没测】在进行json序列化时,会把nil【即指针类型(比如slice、map和*T)的未初始化时的形态】序列化为字符串"null",反序列化时会把字符串"null",如果目标类型是指针类型,则会反序列化为nil

其他测试

知道现象和原因之后,我又测试了些其他的东西 需要注意的是fmt很多时候打印nil的指针类型时不会输出nil,比如nil的slice和map,会打印成[]和map[]

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. jsoniter "github.com/json-iterator/go"
  6. )
  7.  
  8. type Marshaler struct {
  9. A map[string]interface{}
  10. B []string
  11. C [10]int
  12. D *string
  13. E *EE
  14. F string
  15. g string
  16. }
  17. type EE struct {
  18. EEE []string
  19. }
  20.  
  21. func main() {
  22. mal := Marshaler{
  23. E: &EE{},
  24. }
  25. mal1 := &Marshaler{}
  26. e1 := &EE{}
  27. e2 := EE{EEE: []string{}}
  28. var t1 *string
  29. var t2 []int
  30. var t3 map[string]interface{}
  31. var t4 = make([]string, 0)
  32. res1, _ := jsoniter.MarshalToString(mal)
  33. res2, _ := jsoniter.MarshalToString(mal1)
  34. res3, _ := jsoniter.MarshalToString(e1)
  35. res4, _ := jsoniter.MarshalToString(e2)
  36. res5, _ := jsoniter.MarshalToString(t1)
  37. res6, _ := jsoniter.MarshalToString(t2)
  38. res7, _ := jsoniter.MarshalToString(t3)
  39. res8, _ := jsoniter.MarshalToString(t4)
  40. fmt.Printf("res1: %+v\n", res1)
  41. fmt.Printf("res2: %+v\n", res2)
  42. fmt.Printf("res3: %+v\n", res3)
  43. fmt.Printf("res4: %+v\n", res4)
  44. fmt.Printf("res5: %+v\n", res5)
  45. fmt.Printf("res6: %+v\n", res6)
  46. fmt.Printf("res7: %+v\n", res7)
  47. fmt.Printf("res8: %+v\n", res8)
  48.  
  49. params := make(map[string]interface{})
  50. if err := jsoniter.Unmarshal([]byte(res6), &params); err != nil {
  51. fmt.Println("null Unmarshal err:", err)
  52. } else {
  53. fmt.Printf("null Unmarshal map: %+v\n", params)
  54. }
  55.  
  56. if err := jsoniter.Unmarshal([]byte(res6), &mal); err != nil {
  57. fmt.Println("null Unmarshal err:", err)
  58. } else {
  59. fmt.Printf("null Unmarshal Marshaler: %+v\n", mal)
  60. }
  61.  
  62. if err := jsoniter.Unmarshal([]byte(res6), &mal1); err != nil {
  63. fmt.Println("null Unmarshal err:", err)
  64. } else {
  65. fmt.Printf("null Unmarshal Marshaler: %+v\n", mal1)
  66. }
  67.  
  68. if err := jsoniter.Unmarshal([]byte(res6), &t4); err != nil {
  69. fmt.Println("null Unmarshal err:", err)
  70. } else {
  71. fmt.Printf("null Unmarshal []string: %+v\n", t4)
  72. fmt.Println(t4 == nil)
  73. }
  74. }

输出:

res1: {"A":null,"B":null,"C":[0,0,0,0,0,0,0,0,0,0],"D":null,"E":{"EEE":null},"F" :""} res2: {"A":null,"B":null,"C":[0,0,0,0,0,0,0,0,0,0],"D":null,"E":null,"F":""}     res3: {"EEE":null} res4: {"EEE":[]} res5: null res6: null res7: null res8: [] //下面的打印不够准确,看debug截图 null Unmarshal map:  map[] null Unmarshal Marshaler: {A:map[] B:[] C:[0 0 0 0 0 0 0 0 0 0] D:<nil> E:0xc000 004510 F: g:} null Unmarshal Marshaler: <nil> null Unmarshal []string: [] true

Go json反序列化“null“的问题解决

补充说明

默认的反序列化是用float64来接数字类型的,原来的数字太大会出现精度丢失问题

"null"用int或float32等基础数字类型来接会变成默认值0

很多json库在反序列化时都会存在精度丢失问题,比如int64的最后几位变成0,是因为不明确json字符串代表的struct的场景下,用map[string]interface{}来接反序列化之后的内容,会默认用float64来接数字类型,“int64是将64bit的数据全部用来存储数据,但是float64需要表达的信息更多,因此float64单纯用于数据存储的位数将小于64bit,这就导致了float64可存储的最大整数是小于int64的。”,理论上数值超过9007199254740991就可能会出现精度缺失,反序列化时需要针对数字类型单独处理【用struct来接,并且保证类型能对应上就不会有以上问题】:

Go json反序列化“null“的问题解决

到此这篇关于Go json反序列化“null“的问题解决的文章就介绍到这了,更多相关Go json反序列化内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_39618369/article/details/129478386

延伸 · 阅读

精彩推荐
  • Golanggolang 实现并发求和

    golang 实现并发求和

    这篇文章主要介绍了golang 并发求和的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    butterfly52113147102021-06-25
  • GolangGolang操作命令行的几种方式总结

    Golang操作命令行的几种方式总结

    这篇文章主要介绍了Golang操作命令行的几种方式总结,文章通过围主题思想展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下...

    jiaxwu​​​​​​​10412022-11-17
  • Golanggo语言环境搭建简述

    go语言环境搭建简述

    本文简单记录了下go语言环境的搭建流程,给小伙伴们一个参考,希望大家能够喜欢。 ...

    hebedich3592020-04-13
  • Golang解决goxorm无法更新值为默认值的问题

    解决goxorm无法更新值为默认值的问题

    这篇文章主要介绍了解决goxorm无法更新值为默认值的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    zgcbj6402021-03-08
  • GolangGolang的func参数及返回值操作

    Golang的func参数及返回值操作

    这篇文章主要介绍了Golang的func参数及返回值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    懒人程序猿6162021-06-15
  • Golang使用Go实现健壮的内存型缓存的方法

    使用Go实现健壮的内存型缓存的方法

    这篇文章主要介绍了使用Go实现健壮的内存型缓存,本文比较了字节缓存和结构体缓存的优劣势,介绍了缓存穿透、缓存错误、缓存预热、缓存传输、故障转...

    charlieroro10282022-10-09
  • Golang使用go net实现简单的redis通信协议

    使用go net实现简单的redis通信协议

    本文主要介绍了go net实现简单的redis通信协议,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    luslin17117012022-01-19
  • GolangGolang实现for循环运行超时后自动退出的方法

    Golang实现for循环运行超时后自动退出的方法

    for循环对大家来说应该都不陌生,对于golang来说更是必不可少,所以下面这篇文章就来给大家介绍了关于Golang如何实现for循环运行一段时间超时后自动退出...

    小谈3312020-05-11