去json转换实践中遇到的坑

  

在使用去语言开发过程中,经常需要使用到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类型,这显然是不符合我们的预期的。

  

癹son转换实践中遇到的坑"

  

查看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等多个方法。

  

癹son转换实践中遇到的坑”,

  

<>强时间格式

  

对于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包并没有成功将其解析,接下来我们把时间包中支持的所有格式都试一下。

  

癹son转换实践中遇到的坑"

  

经过试验,发现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转换实践中遇到的坑