在使用去语言开发过程中,经常需要使用到json包来进行json和结构的互相转换,在使用过程中,遇到了一些需要额外注意的地方,记录如下。
<强>整数变浮点数问题强>
假设有一个人结构,其中包含int64年龄和体重float64两个字段,现在通过json包将人结构转为map [string]接口{},代码如下。
人型结构{ 名称字符串 年龄int64 体重float64 } 函数main () { 人:=人{ 名称:“吴王”, 年龄:30岁 重量:150.07, } jsonBytes _:=json.Marshal(人) fmt.Println (string (jsonBytes)) var personFromJSON接口{} json。Unmarshal (jsonBytes,和personFromJSON) 接待员:=personFromJSON。(map [string]接口{}) }
代码执行到这里看上去一切正常,但是打印一下map [string]接口{}就会发现不太对了。
fmt.Println (reflect.TypeOf (r(“年龄”)). name ())//float64 fmt.Println (reflect.TypeOf (r(“重量”)). name ())//float64
转换成map [string]接口{}之后,原先的uint64和float64类型都被转换成了float64类型,这显然是不符合我们的预期的。
查看json的规范可以看的到,在json中是没有整型和浮点型之分的,所以现在可以理解json包中的解组方法转出的数字类型为什么都是float64了,因为根据json规范,数字都是同一种类型,那么对应到去的类型中最接近的就是float64了。
json包还针对这个问题提供了更好的解决方案,不过需要使用json。译码器来代替json。解组方法,将json。Unmarhsal替换如下。
var personFromJSON接口{} 解码器:=json.NewDecoder (bytes.NewReader (jsonBytes)) decoder.UseNumber () decoder.Decode(及personFromJSON) 接待员:=personFromJSON。(map [string]接口{})
这种方法首先创建了一个jsonDecoder,然后调用了UseNumber方法,从文档中可以知道,使用UseNumber方法后,json包会将数字转换成一个内置的多类型(而不是float64),这类个数字型提供了转换为int64, float64等多个方法。
,
<>强时间格式强>
对于json格式,是没有时间类型的,日期和时间以json格式存储时,需要转换为字符串类型。这就带来了一个问题,日期时间的字符串表示有多种多样,去的json包支持的是哪一种呢?
使用下面的代码来输出json。元帅方法将时间类型转换为字符串后的格式。
人型结构{ 名称字符串 出生time.Time } 函数main () { 人:=人{ 名称:“吴王”, 出生:time.Now (), } jsonBytes _:=json.Marshal(人) fmt.Println (string (jsonBytes))//{“名称”:“吴王”,“生”:“2018 - 12 - 20 - t16:22:02.00287617 +喂饲"} }
根据输出可以判断,走的json包使用的是RFC3339标准中定义的格式。接下来测试一下json。解组方法所支持的日期时间格式。
dateStr:=" 2018-10-12 " var的人的人 jsonStr:=fmt。Sprintf(“{\“\”, \“吴王\”,\“出生\”:\ " % s \ "} ", dateStr) json.Unmarshal([]字节(jsonStr),和人) fmt.Println (person.Birth)//0001-01-01就是+ 0000 UTC
对于形如2018-10-12的字符串,json包并没有成功将其解析,接下来我们把时间包中支持的所有格式都试一下。
经过试验,发现json。解组方法只支持RFC3339和RFC3339Nano两种格式的转换。还有一个需要注意的地方,使用time.Now()生成的时间是带有一个单调的,经过json。元帅转换时候,由于RFC3339规范里没有存放单调时间的位置,会丢掉这一部分。
<强>对于字段为空的处理强>
json包对于空值的处理是一个非常容易出错的地方,看下面代码。
人型结构{ 名称字符串 年龄int64 出生time.Time 孩子们[]人 } 函数main () { 人:{}=人 jsonBytes _:=json.Marshal(人) fmt.Println (string (jsonBytes))//{" Name ": ",“年龄”:0,“出生”:“0001 - 01 - 01 t00:00:00z”、“孩子”:零} }去json转换实践中遇到的坑