-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
The encoding/json/v2 package release date is yet to be determined, but I think it’s a good time to start thinking about encoding/json/v2 package and its impact on gqlgen.
The encoding/json/v2 package is planned to provide functionality compatible with the encoding/json package, and it seems that the internals of the existing encoding/json package will be built using the encoding/json/v2 package.
This means that gqlgen can benefit from performance improvements without requiring any changes. So far, there are no issues.
The problem arises when gqlgen directly uses the encoding/json/v2 package. I would like to clarify the benefits and issues that may occur in that case.
Reference
golang/go#71497
https://pkg.go.dev/github.com/go-json-experiment/json
Additional Information (edit: added by Steve Coffman)
In #2842 there was a proposal to allow a pluggable JSON implementation for gqlgen. Currently the JSON marshalling cannot be easily replaced with a different implementation such asencoding/json/v2 (or other alternatives). We would like to be able to allow this to be a choice.
As in that proposal, we would add to gqlgen an API that accepts a custom implementation supplied directly to the transport at fields:
type Decoder interface {
Decode(v interface{}) error
UseNumber()
}
type Json interface {
Marshal(v interface{}) ([]byte, error)
NewDecoder(r io.Reader) Decoder
}
type POST struct {
// Map of all headers that are added to graphql response. If not
// set, only one header: Content-Type: application/json will be set.
ResponseHeaders map[string][]string
Json Json // Json being an interface so it can be implemented however the user wants
}The library can then supply a default implementation based on encoding/json:
var DefaultJson Json = jsonImpl{}
type jsonImpl struct{}
func (jsonImpl) Marshal(v interface{}) ([]byte, error) {
return json.Marshal(v)
}
func (jsonImpl) NewDecoder(r io.Reader) Decoder {
return json.NewDecoder(r)
}Since there already exists a file that handles most JSON marshalling, it can be updated to accept that JSON implementation and fallback if one is not supplied:
func writeJson(json Json, w io.Writer, response *graphql.Response) {
if json == nil {
json = DefaultJson
}
b, err := json.Marshal(response)
if err != nil {
panic(err)
}
w.Write(b)
}This will add a slight overhead of checking for the implementation, but will not break existing codebases.
This will also allow us to easily add a go version build tag when encoding/json/v2 is released, such that we can immediately upgrade to it if that Go version is available.