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

目录
  • 实验
  • 其他测试

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

func mergeContent(inputJson string, inputMap map[string]interface{}) (map[string]interface{}, error) {
	jsonMap := make(map[string]interface{})
	if inputJson != "" {
		decoder := jsoniter.NewDecoder(strings.NewReader(inputJson))
		decoder.UseNumber()
		if err := decoder.Decode(&jsonMap); err != nil {
			return nil, err
		}
	}
	//merge
	for k, v := range inputMap {
		jsonMap[k] = v
	}
	return jsonMap, nil
}

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

实验

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

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

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

其他测试

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

package main

import (
   "fmt"
   jsoniter "github.com/json-iterator/go"
)

type Marshaler struct {
   A map[string]interface{}
   B []string
   C [10]int
   D *string
   E *EE
   F string
   g string
}
type EE struct {
   EEE []string
}

func main() {
   mal := Marshaler{
      E: &EE{},
   }
   mal1 := &Marshaler{}
   e1 := &EE{}
   e2 := EE{EEE: []string{}}
   var t1 *string
   var t2 []int
   var t3 map[string]interface{}
   var t4 = make([]string, 0)
   res1, _ := jsoniter.MarshalToString(mal)
   res2, _ := jsoniter.MarshalToString(mal1)
   res3, _ := jsoniter.MarshalToString(e1)
   res4, _ := jsoniter.MarshalToString(e2)
   res5, _ := jsoniter.MarshalToString(t1)
   res6, _ := jsoniter.MarshalToString(t2)
   res7, _ := jsoniter.MarshalToString(t3)
   res8, _ := jsoniter.MarshalToString(t4)
   fmt.Printf("res1: %+v\n", res1)
   fmt.Printf("res2: %+v\n", res2)
   fmt.Printf("res3: %+v\n", res3)
   fmt.Printf("res4: %+v\n", res4)
   fmt.Printf("res5: %+v\n", res5)
   fmt.Printf("res6: %+v\n", res6)
   fmt.Printf("res7: %+v\n", res7)
   fmt.Printf("res8: %+v\n", res8)

   params := make(map[string]interface{})
   if err := jsoniter.Unmarshal([]byte(res6), &params); err != nil {
      fmt.Println("null Unmarshal err:", err)
   } else {
      fmt.Printf("null Unmarshal map:  %+v\n", params)
   }

   if err := jsoniter.Unmarshal([]byte(res6), &mal); err != nil {
      fmt.Println("null Unmarshal err:", err)
   } else {
      fmt.Printf("null Unmarshal Marshaler: %+v\n", mal)
   }

   if err := jsoniter.Unmarshal([]byte(res6), &mal1); err != nil {
      fmt.Println("null Unmarshal err:", err)
   } else {
      fmt.Printf("null Unmarshal Marshaler: %+v\n", mal1)
   }

   if err := jsoniter.Unmarshal([]byte(res6), &t4); err != nil {
      fmt.Println("null Unmarshal err:", err)
   } else {
      fmt.Printf("null Unmarshal []string: %+v\n", t4)
      fmt.Println(t4 == nil)
   }
}

输出:

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

补充说明

默认的反序列化是用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反序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go语言对JSON数据进行序列化和反序列化

    golang中对json的序列化/反序列化操作还是比较容易的,序列化操作主要是通过encoding/json包的Marshal()方法来实现,反序列化操作主要是通过encoding/json包的Unmarshal()方法来实现. //JSON序列化和反序列化 //可用在api序列化输出 //转成结构体,方便程序操作等 package main import ( "encoding/json" "fmt" ) type Response1 struct { Page

  • Golang中Json的序列化和反序列化的使用

    目录 JSON: 创建格式: 基本数据类型序列化: map序列化: 切片序列化: 反序列化为结构体: 反序列化为map: 反序列化为切片: JSON: JSON(JavaScript Object Notation):是一种轻量级的数据交换格式. 它是基于 ECMAScript 规范的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据. 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言.易于人阅读和编写,同时也易于计算机解析和生成,并有效的 提升网络传输效率. Json易于机器

  • golang中json反序列化可能遇到的问题

    前言 在golang中,当浮点数超过一定数值的时候,golang会把它弄成科学计数法的形式进行显示(好像只要大于七位数就变成科学计数法了) var val float64 val = 1000000 fmt.Println(val) // ==> 1e+06 而在日常开发中,我们经常遇到这样一个问题,就是要反序列化前端传递来的json,因为数据结构未知,所以我们便会使用map[string]interface{}来接收反序列化的结果.由于golang将json解析到interface{}类型的时

  • golang:json 反序列化的[]和nil操作

    我就废话不多说了,大家还是直接看代码吧~ package main import ( "encoding/json" "log" ) type JS struct { A []string } func main() { v1 := &JS{} v2 := &JS{A: []string{}} o1, err := json.Marshal(&v1) log.Println(string(o1), err) o2, err2 := json.

  • Go语言基础Json序列化反序列化及文件读写示例详解

    目录 概述 JSON序列化 结构体转JSON map转JSON 切片转JSON JSON反序列化 JSON转map JSON转结构体 JSON转切片 写JSON文件 map写入JSON文件 切片写入JSON文件 结构体写入JSON文件 读JSON文件 解码JSON文件为map 解码JSON文件为切片 解码JSON文件为结构体 示例 概述 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的.键值对的数据交换格式.结构由大括号'{}',中括

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

    目录 实验 其他测试 有这么一段代码,可以先看一下有没有什么问题,作用是输入一段json字符串,反序列化成map,然后将另一个inputMap的内容,merge进这个map func mergeContent(inputJson string, inputMap map[string]interface{}) (map[string]interface{}, error) { jsonMap := make(map[string]interface{}) if inputJson != "&qu

  • 实例解析Json反序列化之ObjectMapper(自定义实现反序列化方法)

    对于服务器端开发人员而言,调用第三方接口获取数据,将其"代理"转化并返给客户端几乎是家常便饭的事儿.    一般情况下,第三方接口返回的数据类型是json格式,而服务器开发人员则需将json格式的数据转换成对象,继而对其进行处理并封装,以返回给客户端. 在不是特别考虑效率的情况下(对于搜索.缓存等情形可以考虑使用thrift和protobuffer),通常我们会选取jackson包中的ObjectMapper类对json串反序列化以得到相应对象.通常会选取readValue(Strin

  • Swift 中的 JSON 反序列化示例详解

    目录 业界常用的几种方案 手动解码方案,如 Unbox(DEPRECATED) 阿里开源的 HandyJSON 基于 Sourcery 的元编程方案 Swift build-in API Codable 属性装饰器,如 BetterCodable 各个方案优缺点对比 Codable 介绍 原理浅析 Decoder.Container 协议 自研方案 功能设计 Decoder.Container 具体实现 再议 PropertyWrapper 应用场景示例 单元测试 性能对比 业界常用的几种方案

  • fastjson生成json时Null属性不显示的解决方法

    举个例子 Map < String , Object > jsonMap = new HashMap< String , Object>(); jsonMap.put("a",1); jsonMap.put("b",""); jsonMap.put("c",null); jsonMap.put("d","wuzhuti.cn"); String str = JSO

  • jackson 实体转json 为NULL或者为空不参加序列化(实例讲解)

    使用jackson进行序列化时,往往会遇到后台某个实体对象的属性为null,当序列化成json时对应的属性也为null:这样在某些前端组件上应用该json对象会报错.(例如:echarts) 下面总结了两种方法,解决了当属性为null时不参与序列化: 方法一: 1.实体上使用如下注解 @JsonInclude(Include.NON_NULL) 将该标记放在属性上,如果该属性为NULL则不参与序列化 :如果放在类上边,那对这个类的全部属性起作用. 具体取值有: //Include.Include

  • C#中Json反序列化的实现方法

    前言 Json反序列化有两种方式[本人],一种是生成实体的,方便处理大量数据,复杂度稍高,一种是用匿名类写,方便读取数据,较为简单. 使用了Newtonsoft.Json,可以自行在nuget中导入 Json源数据: var data = "{'jingdong_ldop_receive_trace_get_responce':{'code':'0','querytrace_result':{'data':[{'opeTitle':'快递签收','opeRemark':'货物已交付京东物流','

  • SpringBoot项目中处理返回json的null值(springboot项目为例)

    在后端数据接口项目开发中,经常遇到返回的数据中有null值,导致前端需要进行判断处理,否则容易出现undefined的情况,如何便捷的将null值转换为空字符串? 以SpringBoot项目为例,SSM同理. 1.新建配置类(JsonConfig.java) import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.f

  • python json.dumps中文乱码问题解决

    json.dumps(var,ensure_ascii=False)并不能解决中文乱码的问题 json.dumps在不同版本的Python下会有不同的表现, 注意下面提到的中文乱码问题在Python3版本中不存在. 注:下面的代码再python 2.7版本下测试通过 # -*- coding: utf-8 -*- odata = {'a' : '你好'} print odata 结果: {'a': '\xe4\xbd\xa0\xe5\xa5\xbd'} print json.dumps(odat

  • JSON反序列化Long变Integer或Double的问题及解决

    目录 一.背景 二.研究 三.如何解决 3.0 将类型写入 JSON 字符串中 3.1 提供 POJO 类,慎对 Map<String,Object> 序列化 3.2 反序列化自定义类 3.3 其他 一.背景 工作中可能会遇到对 Map<String,Object> 进行 JSON 序列化,其中值中包含 Long 类型的数据,反序列化后强转 Long 时报类型转换异常的问题. 本文简单探讨下该问题,并给出解决方案,如果你想直接看建议,直接翻到第三部分即可. 二.研究 本文主要以 j

  • MySQL中CONCAT()函数拼接出现NULL的问题解决

    项目中查询用到了concat()拼接函数,在此查询中出现了拼接的字段为null的情况,拼接结果为null在应用层报了空指针异常. SELECT CONCAT('1,',NULL,'2') result; SELECT CONCAT('1,','','2') result; 通过实践证明CONCAT()函数拼接时如果拼接的参数中有NULL时,结果为NULL. 使用以下方式来解决 方法一:使用IFNULL函数如果是NULL将其置为''空字符串. SELECT CONCAT('1,',IFNULL(N

随机推荐