网页 综合 更新时间 2026-11-14 03:59:00

A new Go API for JSON - The Go Programming Language

自动蜘蛛 go.dev 正文约 6000 字
Common problems companies solve with Go
Stories about how and why companies use Go
How Go can help keep you secure by default
The official Go language specification
A complete introduction to building software with Go
Reference documentation for Go's standard library
Learn what's new in each Go release
Tips for writing clear, performant, and idiomatic Go code
Videos from prior events
Meet other local Go developers
Learn and network with Go developers from around the world
The Go project's official blog.
Get help and stay informed from Go
Michael Pratt, Joe Tsai, Daniel Martí, Johan Brandhorst-Satzkorn, Roger Peppe, Chris Hines, and Damien Neil 4 November 2026
JavaScript Object Notation (JSON) is a simple data interchange format, the most popular data format used on the internet, and widely read and written by Go programs. Go has included support for JSON in the standard library since well before Go 1.0. We first wrote about support for JSON in Go more than 15 years ago!
Over time, packages evolve with the needs of their users, and encoding/json is no exception. Last year, we wrote about a new experimental API for JSON designed to bring long-awaited improvements and fixes.
After additional feedback and refinement, the new encoding/json/v2 and encoding/json/jsontext packages are stable and generally available in Go 1.27! This post is an updated version of the article introducing the experiment, describing the problems with encoding/json and introducing the new packages.
Overall, encoding/json has held up well. The idea of marshaling and unmarshaling arbitrary Go types with some default representation in JSON, combined with the ability to customize the representation, has proven to be highly flexible. However, in the years since its introduction, various users have identified numerous shortcomings.
There are various behavioral flaws in encoding/json:
Imprecise handling of JSON syntax: Over the years, JSON has seen increased standardization in order for programs to properly communicate. Generally, decoders have become stricter at rejecting ambiguous inputs, to reduce the chance that two implementations will have different (successful) interpretations of a particular JSON value.
encoding/json currently accepts invalid UTF-8, whereas the latest Internet Standard (RFC 8259) requires valid UTF-8. The default behavior should report an error in the presence of invalid UTF-8, instead of introducing silent data corruption, which may cause problems downstream.
encoding/json currently accepts objects with duplicate member names. RFC 8259 does not specify how to handle duplicate names, so an implementation is free to choose an arbitrary value, merge the values, discard the values, or report an error. The presence of a duplicate name results in a JSON value without a universally agreed upon meaning. This could be exploited by attackers in security applications and has been exploited before (as in CVE-2017-12635). The default behavior should err on the side of safety and reject duplicate names.
Leaking nilness of slices and maps: JSON is often used to communicate with programs using JSON implementations that do not allow null to be unmarshaled into a data type expected to be a JSON array or object. Since encoding/json marshals a nil slice or map as a JSON null, this may lead to errors when unmarshaling by other implementations. A survey indicated that most Go users prefer that nil slices and maps are marshaled as an empty JSON array or object by default.
Case-insensitive unmarshaling: When unmarshaling, a JSON object member name is resolved to a Go struct field name using a case-insensitive match. This is a surprising default, a potential security vulnerability, and a performance limitation.
Inconsistent calling of methods: Due to an implementation detail, MarshalJSON methods declared on a pointer receiver are inconsistently called by encoding/json. While regarded as a bug, this cannot be fixed as too many applications depend on the current behavior.
The API of encoding/json can be tricky or restrictive:
It is difficult to correctly unmarshal from an io.Reader. Users often write json.NewDecoder(r).Decode(v), which fails to reject trailing junk at the end of the input.
Options can be set on the Encoder and Decoder types, but cannot be used with the Marshal and Unmarshal functions. Similarly, types implementing the Marshaler and Unmarshaler interfaces cannot make use of the options and there is no way to plumb options down the call stack. For example, the Decoder.DisallowUnknownFields option loses its effect when calling a custom UnmarshalJSON method.
The Compact, Indent, and HTMLEscape functions write to a bytes.Buffer instead of something more flexible like a []byte or io.Writer. This limits the usability of those functions.
Setting aside internal implementation details, the public API commits it to certain performance limitations:
MarshalJSON: The MarshalJSON interface method forces the implementation to allocate the returned []byte. Also, the semantics require that encoding/json verify that the result is valid JSON and also to reformat it to match the specified indentation.
UnmarshalJSON: The UnmarshalJSON interface method requires that a complete JSON value be provided (without any trailing data). This forces encoding/json to parse the JSON value to be unmarshaled in its entirety to determine where it ends before it can call UnmarshalJSON. Afterwards, the UnmarshalJSON method itself must parse the provided JSON value again.
Lack of streaming: Even though the Encoder and Decoder types operate on an io.Writer or io.Reader, they buffer the entire JSON value in memory. The Decoder.Token method for reading individual tokens is allocation-heavy and there is no corresponding API for writing tokens.
Furthermore, if the implementation of a MarshalJSON or UnmarshalJSON method recursively calls the Marshal or Unmarshal function, then the performance becomes quadratic.
Introducing a new, incompatible major versio
访问原文 返回搜索 https://go.dev/blog/jsonv2
本页为82搜索生成的网页快照,内容来自站内索引;演示数据的原文链接仅作示例。