- Notifications
You must be signed in to change notification settings - Fork28
Experimental implementation of a proposed v2 encoding/json package
License
go-json-experiment/json
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This module hosts an experimental implementation of v2encoding/json.The API is unstable and breaking changes will regularly be made.Do not depend on this in publicly available modules.
Any commits that make breaking API or behavior changes will be markedwith the string "WARNING: " near the top of the commit message.It is your responsibility to inspect the list of commit changeswhen upgrading the module. Not all breaking changes will lead to build failures.
Aproposal to include this module in Go asencoding/json/v2 andencoding/json/jsontext has been started on the Go Github project on 2025-01-30. Please provide your feedback there.At present, this module is available within the Go standard library as a Go experiment.See"A new experimental Go API for JSON" for more details.
Mostly backwards compatible: If possible, v2 should aim to bemostlycompatible with v1 in terms of both API and default behavior to ease migration.For example, the
MarshalandUnmarshalfunctions are the most widely useddeclarations in the v1 package. It seems sensible for equivalent functionalityin v2 to be named the same and have a mostly compatible signature.Behaviorally, we should aim for 95% to 99% backwards compatibility.We do not aim for 100% compatibility since we want the freedom to breakcertain behaviors that are now considered to have been a mistake.Options exist that can bring the v2 implementation to 100% compatibility,but it will not be the default.More flexible: There is along list of feature requests.We should aim to provide the most flexible features that addresses most usages.We do not want to over fit the v2 API to handle every possible use case.Ideally, the features provided should be orthogonal in nature such thatany combination of features results in as few surprising edge cases as possible.
More performant: JSON serialization is widely used and any bit of extraperformance gains will be greatly appreciated. Some rarely used behaviors of v1may be dropped in favor of better performance. For example,despite
EncoderandDecoderoperating on anio.Writerandio.Reader,they do not operate in a truly streaming manner,leading to a loss in performance. The v2 implementation should aim to be trulystreaming by default (see#33714).Easy to use (hard to misuse): The v2 API should aim to makethe common case easy and the less common case at least possible.The API should avoid behavior that goes contrary to user expectation,which may result in subtle bugs (see#36225).
v1 and v2 maintainability: Since the v1 implementation must stay forever,it would be beneficial if v1 could be implemented under the hood with v2,allowing for less maintenance burden in the future. This probably implies thatbehavioral changes in v2 relative to v1 need to be exposed as options.
Avoid unsafe: Standard library packages generally avoid the use ofpackage
unsafeeven if it could provide a performance boost.We aim to preserve this property.
While this module aims to possibly be the v2 implementation ofencoding/json,there is no guarantee that this outcome will occur. As with any major changeto the Go standard library, this will eventually go through theGo proposal process.At the present moment, this is still in the design and experimentation phaseand is not ready for a formal proposal.
There are several possible outcomes from this experiment:
- We determine that a v2
encoding/jsonwould not provide sufficient benefitover the existing v1encoding/jsonpackage. Thus, we abandon this effort. - We propose a v2
encoding/jsondesign, but it is rejected in favor of someother design that is considered superior. - We propose a v2
encoding/jsondesign, but rather than adding an entirelynew v2encoding/jsonpackage, we decide to merge its functionality intothe existing v1encoding/jsonpackage. - We propose a v2
encoding/jsondesign and it is accepted, resulting inits addition to the standard library. - Some other unforeseen outcome (among the infinite number of possibilities).
This module is primarily developed by@dsnet,@mvdan, and@johanbrandhorstwith feedback provided by@rogpeppe,@ChrisHines, and@rsc.
Discussion about semantics occur semi-regularly, where arecord of past meetings can be found here.
This package aims to provide a clean separation between syntax and semantics.Syntax deals with the structural representation of JSON (as specified inRFC 4627,RFC 7159,RFC 7493,RFC 8259, andRFC 8785).Semantics deals with the meaning of syntactic data as usable application data.
TheEncoder andDecoder types are streaming tokenizers concerned with thepacking or parsing of JSON data. They operate onToken andValue typeswhich represent the common data structures that are representable in JSON.Encoder andDecoder do not aim to provide any interpretation of the data.
Functions likeMarshal,MarshalWrite,MarshalEncode,Unmarshal,UnmarshalRead, andUnmarshalDecode provide semantic meaning by correlatingany arbitrary Go type with some JSON representation of that type (as stored indata types like[]byte,io.Writer,io.Reader,Encoder, orDecoder).
This diagram provides a high-level overview of the v2json andjsontext packages.Purple blocks represent types, while blue blocks represent functions or methods.The arrows and their direction represent the approximate flow of data.The bottom half of the diagram contains functionality that is only concernedwith syntax (implemented by thejsontext package),while the upper half contains functionality that assignssemantic meaning to syntactic data handled by the bottom half(as implemented by the v2json package).
In contrast to v1encoding/json, options are represented as separate typesrather than being setter methods on theEncoder orDecoder types.Some options affects JSON serialization at the syntactic layer,while others affect it at the semantic layer.Some options only affect JSON when decoding,while others affect JSON while encoding.
The v2json package changes the default behavior ofMarshal andUnmarshalrelative to the v1json package to be more sensible.Some of these behavior changes have options and workarounds to opt intobehavior similar to what v1 provided.
This table shows an overview of the changes:
| v1 | v2 | Details |
|---|---|---|
| JSON object members are unmarshaled into a Go struct using acase-insensitive name match. | JSON object members are unmarshaled into a Go struct using acase-sensitive name match. | CaseSensitivity |
When marshaling a Go struct, a struct field marked asomitempty is omitted ifthe field value is an empty Go value, which is defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string. | When marshaling a Go struct, a struct field marked asomitempty is omitted ifthe field value would encode as an empty JSON value, which is defined as a JSON null, or an empty JSON string, object, or array. | OmitEmptyOption |
Thestring optiondoes affect Go strings and bools. | Thestring optiondoes not affect Go strings or bools. | StringOption |
Thestring optiondoes not recursively affect sub-values of the Go field value. | Thestring optiondoes recursively affect sub-values of the Go field value. | StringOption |
Thestring optionsometimes accepts a JSON null escaped within a JSON string. | Thestring optionnever accepts a JSON null escaped within a JSON string. | StringOption |
| A nil Go slice is marshaled as aJSON null. | A nil Go slice is marshaled as anempty JSON array. | NilSlicesAndMaps |
| A nil Go map is marshaled as aJSON null. | A nil Go map is marshaled as anempty JSON object. | NilSlicesAndMaps |
| A Go array may be unmarshaled from aJSON array of any length. | A Go array must be unmarshaled from aJSON array of the same length. | Arrays |
| A Go byte array is represented as aJSON array of JSON numbers. | A Go byte array is represented as aBase64-encoded JSON string. | ByteArrays |
MarshalJSON andUnmarshalJSON methods declared on a pointer receiver areinconsistently called. | MarshalJSON andUnmarshalJSON methods declared on a pointer receiver areconsistently called. | PointerReceiver |
| A Go map is marshaled in adeterministic order. | A Go map is marshaled in anon-deterministic order. | MapDeterminism |
| JSON strings are encodedwith HTML-specific characters being escaped. | JSON strings are encodedwithout any characters being escaped (unless necessary). | EscapeHTML |
| When marshaling, invalid UTF-8 within a Go stringare silently replaced. | When marshaling, invalid UTF-8 within a Go stringresults in an error. | InvalidUTF8 |
| When unmarshaling, invalid UTF-8 within a JSON stringare silently replaced. | When unmarshaling, invalid UTF-8 within a JSON stringresults in an error. | InvalidUTF8 |
| When marshaling,an error does not occur if the output JSON value contains objects with duplicate names. | When marshaling,an error does occur if the output JSON value contains objects with duplicate names. | DuplicateNames |
| When unmarshaling,an error does not occur if the input JSON value contains objects with duplicate names. | When unmarshaling,an error does occur if the input JSON value contains objects with duplicate names. | DuplicateNames |
| Unmarshaling a JSON null into a non-empty Go valueinconsistently clears the value or does nothing. | Unmarshaling a JSON null into a non-empty Go valuealways clears the value. | MergeNull |
| Unmarshaling a JSON value into a non-empty Go valuefollows inconsistent and bizarre behavior. | Unmarshaling a JSON value into a non-empty Go valuealways merges if the input is an object, and otherwise replaces. | MergeComposite |
Atime.Duration is represented as aJSON number containing the decimal number of nanoseconds. | Atime.Duration has no default representation in v2 (see#71631) and results in an error. | |
| A Go struct with only unexported fieldscan be serialized. | A Go struct with only unexported fieldscannot be serialized. | EmptyStructs |
Seediff_test.go for details about every change.
One of the goals of the v2 module is to be more performant than v1,but not at the expense of correctness.In general, v2 is at performance parity with v1 for marshaling,but dramatically faster for unmarshaling.
Seehttps://github.com/go-json-experiment/jsonbench for benchmarkscomparing v2 with v1 and a number of other popular JSON implementations.
About
Experimental implementation of a proposed v2 encoding/json package
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Contributors9
Uh oh!
There was an error while loading.Please reload this page.
