当前位置:网站首页>Go json. Decoder Considered Harmful
Go json. Decoder Considered Harmful
2022-07-28 10:38:00 【Fireflywang】
If you're using Go Language programming , And use json.Decoder Inverse solution JSON load , You may have unexpected effects . You should use json.Unmarshal Instead of json.Decoder.
- json.Decoder It is designed to solve JSON flow , Not complete JSON object .
- json.Decoder Will ignore some illegal JSON grammar .
- json.Decoder The network connection is not released for reuse ( It will slow down HTTP Request to about 4 Multiple duration ).
If you get through json Package documentation , You won't be surprised , Such is the case . I have made mistakes many times . Most developers find using json.Decoder.Decode(...) Than using json.Unmarshal(...) It's easier to parse io.Reader type .
1. json.Decoder by JSON Flow design
JSON Streams are generally in series (concatenated) Or split with a new line JSON value . Here is an example :
{"Name":"Ed"}{"Name":"Sam"}{"Name":"Bob"} Complete streaming content is not a legal JSON, Only the outermost layer is used [ ] It is legal to surround JSON type .
It's just in series JSON object , let me put it another way , It's legal JSON flow .
json.Decoder The type is specially designed for JSON flow . The most likely thing , Yours JSON The load is not suitable for this .
that JSON Why does flow exist ? Can't we use JSON Array ?JSON Stream is mainly used in :
- Store structured data in files , And quickly append without completely parsing the entire file
- from API And other real-time structured streaming data ( Such as
docker logs/docker eventsAPI Wait is to use this method )
If you are parsing a single complete JSON object , Do not use json.Decoder.
2. json.Decoder Will ignore illegal syntax
Not to ignore all illegal grammar , But mixed illegal and legal grammar JSON Flow will be json.Decoder Ignore mistakes . For example, suppose a API return :
{"Name": "Bob"}But the service introduces bug, All of a sudden, it's coming back
{}{"Name": "Bob"}This is obviously illegal JSON load , But it is a legal JSON flow ,json.Decoder Acceptable .
But you don't know this situation , Your code will reverse this return to complete JSON object :
type Person struct {Name string}
...
var v Person
if err := dec.Decode(&v); err != nil {
panic(err)
}
fmt.Println(v.Name) You will get v.Name Is an empty string , There is no mistake .json.Decoder It reverses the first JSON object , The rest is ignored .
Can this happen ? Maybe not , But you can 100% Are you sure? ? Because when it happens, you can't easily debug come out .
3. json.Decoder Not properly exhausted HTTP Connect
This problem was recently solved by Flippo Valsorda Bring up (link), You may be affected by this , Unless you're using Go 1.7 (or above, translator's note ).
If you are creating a HTTP request , Transfer the return body to json.Decoder#Decode() ( Most people will do this ) Then it is very likely that your connection has not been properly exhausted , May make your HTTP The client is slow 4 times .
If HTTP The endpoint returns a single complete JSON object , And you only call json.Decoder#Decode() once , This may mean that you have not read io.EOF Return signal . So you have no basis io.EOF End json.Decoder, The returnee is still open ,TCP Connect ( Or others in use Transport) It cannot be returned to the connection pool even if you have finished reading . For more information, please click URL.
Now in golang The main branch master Has been fixed in , Most likely in Go1.7 In the release .( This article is written in 2016 year 4 month 28 Japan , That fashion has not been released Go1.7)
meanwhile , If your returnee is small enough , Only need to use ioutil.ReadAll Read all into memory and use json.Unmarshal Inverse solution . If you want to keep using json.Decoder, You need to exhaust the unread part of the return body , for example :
io.Copy(ioutil.Discard, resp.Body) therefore , If you are using json.Decoder, Please check your code , Will all defer resp.Body.Close() Replace with :
defer func() {
io.Copy(ioutil.Discard, resp.Body)
resp.Body.Close()
}Conclusion
If you don't handle JSON flow , Please do not use json.Decoder.
Use json.Unmarshal:
- If you don't know Go JSON What is flow
- If you are dealing with a single JSON object
- If remote API It is possible to return the problem JSON
Now you know the trade-off strategy , Then decide for yourself .
Reference material
边栏推荐
- 机器学习--手写英文字母2--导入与处理数据
- a different object with the same identifier value was already associated with the session
- Ie compatibility problem handling
- 爱可可AI前沿推介(7.28)
- Uni app project directory, file function introduction and development specification
- KingbaseES V8R6 JDBC 能否使用VIP ?
- 6、MapReduce自定义分区实现
- brief introduction
- Deadlock algorithm: banker algorithm and security algorithm
- Differences among pipes, pipe passes and pipe States
猜你喜欢

SQL Server 2016 学习记录 --- 集合查询

Shortest path topic

ACM winter vacation training 5

SDUT Round 9 2020 Spring Festival campaign

Match file names from file paths using regular expressions

3、MapReduce详解与源码分析

第一篇:UniAPP的小程序跨端开发-----创建uniapp项目

Idea create my first project

Get to know SuperMap idesktop for the first time

SQL Server 2016学习记录 --- 单表查询
随机推荐
20200217 training match L1 - 7 2019 is coming (20 points)
AP Autosar平台设计 3架构
Troubleshooting of tool failure caused by Chinese characters in PT kill query
Implement a queue with two stacks [C language]
Context values traps and how to avoid or mitigate these traps in go
Inverse element & combinatorial number & fast power
3、MapReduce详解与源码分析
机器学习--手写英文字母3--工程特点
Excel word 简单 技巧 整理(持续更新 大概~)
Can kingbasees v8r6 JDBC use VIP?
Pat grade a title in September 2019
ICML 2022 | 图表示学习的结构感知Transformer模型
Ueeditor v1.4.3 control file compression
gcc: error trying to exec 'as': execvp: No such file or directory
Typora tutorial
CentOS7下安装mysql5.7
SQL Server 2016 学习记录 --- 嵌套查询
C language secondary pointer explanation and example code
用两个栈实现一个队列【C语言】
287. Find the Duplicate Number