This is a creation in Article, where the information may have evolved or changed.
The JSON parsing of Go is extremely simple compared to many languages.
Problem
In general, we often do this with JSON decoding in Go:
Package Mainimport "Encoding/json"//Jsontext comes from http://json.org/example.htmlvar jsontext = []byte (' {' glossary ') : {"title": "Example Glossary", "Glossdiv": {"title": "S", "glosslist": {"Glossentry": { "ID": "SGML", "Sortas": "SGML", "glossterm": "Standard generalized Markup Language "," acronym ":" SGML "," abbrev ":" ISO 8879:1986 "," Glossdef ": {" pa RA ":" A meta-markup language, used to create markup languages such as DocBook. "," glossseealso ": [ "GML", "XML"}, "Glosssee": "Markup" }}}}} ') type glossary struct {glossary struct {title string ' JSON: ' title ' ' Glos SDiv struct {title string ' JSON: ' title ' ' glosslist struct {glossentry struct { Id String ' JSON: ' ID ' ' Sortas string ' json: ' Sortas ' ' glossterm string ' JSON: ' Glo Ssterm "' Acronym string ' JSON:" acronym "' Abbrev string ' JSON:" Abbrev "' glossdef struct {Para string ' JSON: "Para" ' Glossseeal So []string ' JSON: "Glossseealso" '} ' JSON: "Glossdef" ' Glosssee string ' JSON: "Glossse E "'} ' JSON:" Glossentry "'} ' JSON:" Glosslist "'} ' JSON:" Glossdiv "'} ' JSON:" Glossary "' }func Main () {var g glossary json. Unmarshal (Jsontext, &g)}
This kind of decoding for our daily use seems to have no problem, at least can use? For a piece of JSON, we don't have to decode all the parts immediately, what do you mean?
With the example code above, we decode the jsontext and probably just need to use Title and glossdiv.title right away. So what do we do with this situation?
package mainimport "encoding/json"// jsonText comes from http://json.org/example.htmlvar jsonText = []byte(`{ ... // 此处省略, 同上}`)type glossarySectional struct { Glossary struct { Title string `json:"title"` GlossDiv struct { Title string `json:"title"` GlossList json.RawMessage `json:"GlossList"` // diff: delay JSON decoding } `json:"GlossDiv"` } `json:"glossary"`}func main() { var g glossarySectional json.Unmarshal(jsonText, &g)}
Yes, the magic is here GlossList json.RawMessage
. Let's see what the documentation says:
Rawmessage is a raw encoded JSON value. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.
At a glance, Rawmessage plays the role of delaying decoding a JSON value. So you might say, what's the use of this?
This may not be a problem for normal decoding, but for some, like message passing (KAFKA), subtle delays can have a big impact. We can test this subtle difference with a simple benchmark:
// 其他代码略 ... 完整代码参见: http://bit.ly/2skxY9L .func benchmarkJSONUnmarshal(f func(), b *testing.B) { for n := 0; n < b.N; n++ { f() }}func BenchmarkJSONUnmarshal_0(b *testing.B) { benchmarkJSONUnmarshal(func() { var g glossary json.Unmarshal(jsonText, &g) }, b)}func BenchmarkJSONUnmarshal_1(b *testing.B) { benchmarkJSONUnmarshal(func() { var g glossarySectional json.Unmarshal(jsonText, &g) }, b)}
We go test -run=NONE -bench=. ./...
can conclude by running (slightly different environments):
BenchmarkJSONUnmarshal_0-8 200000 10565 ns/opBenchmarkJSONUnmarshal_1-8 200000 7699 ns/op
Difference Range:
benchmark old ns/op new ns/op deltaBenchmarkJSONUnmarshal-8 10298 7591 -26.29%
It can be seen that this difference is still very large, especially when the JSON body is very large.
Conclusion
For some of the performance-related JSON parsing processing, we can json.RawMessage
improve performance.