Skip to content

Commit

Permalink
codec: allow user to override default JSON serializer (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew-M-C committed Jan 15, 2024
1 parent 65a60b1 commit 26b9e07
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 15 deletions.
26 changes: 22 additions & 4 deletions codec/serialization_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,35 @@
package codec

import (
"encoding/json"

jsoniter "github.com/json-iterator/go"
)

// JSONAPI is json packing and unpacking object, users can change
// the internal parameter.
var JSONAPI = jsoniter.ConfigCompatibleWithStandardLibrary
var JSONAPI JSONSerializer = jsoniter.ConfigCompatibleWithStandardLibrary

// JSONSerializer is json packing and unpacking object interface
type JSONSerializer interface {
Unmarshal([]byte, interface{}) error
Marshal(interface{}) ([]byte, error)
}

// StandardJSONSerializer is a JSONSerializer using standard encoding/json.
type StandardJSONSerializer struct{}

// Unmarshal deserializes the in bytes into body.
func (StandardJSONSerializer) Unmarshal(in []byte, body interface{}) error {
return json.Unmarshal(in, body)

Check warning on line 37 in codec/serialization_json.go

View check run for this annotation

Codecov / codecov/patch

codec/serialization_json.go#L36-L37

Added lines #L36 - L37 were not covered by tests
}

// Marshal returns the serialized bytes in json protocol.
func (StandardJSONSerializer) Marshal(body interface{}) ([]byte, error) {
return json.Marshal(body)

Check warning on line 42 in codec/serialization_json.go

View check run for this annotation

Codecov / codecov/patch

codec/serialization_json.go#L41-L42

Added lines #L41 - L42 were not covered by tests
}

// JSONSerialization provides json serialization mode.
// golang official json package is implemented by reflection,
// and has very low performance. So trpc-go choose json-iterator package
// to implement json serialization.
type JSONSerialization struct{}

// Unmarshal deserializes the in bytes into body.
Expand Down
50 changes: 39 additions & 11 deletions restful/serialize_jsonpb.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package restful

import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"strconv"
Expand All @@ -35,9 +36,36 @@ type JSONPBSerializer struct {
AllowUnmarshalNil bool // allow unmarshalling nil body
}

// JSONAPI is a copy of jsoniter.ConfigCompatibleWithStandardLibrary.
// github.com/json-iterator/go is faster than Go's standard json library.
var JSONAPI = jsoniter.ConfigCompatibleWithStandardLibrary
// JSONAPI is json packing and unpacking object, users can deside you own JSON

Check warning on line 39 in restful/serialize_jsonpb.go

View workflow job for this annotation

GitHub Actions / typos

"deside" should be "decide".
// serialization implementation.
var JSONAPI JSONSerializer = jsoniter.ConfigCompatibleWithStandardLibrary

// JSONSerializer is json packing and unpacking object interface
type JSONSerializer interface {
Unmarshal([]byte, interface{}) error
Marshal(interface{}) ([]byte, error)
MarshalIndent(v any, prefix, indent string) ([]byte, error)
}

// StandardJSONSerializer is a JSONSerializer using standard encoding/json.
type StandardJSONSerializer struct{}

// Unmarshal deserializes the in bytes into body.
func (StandardJSONSerializer) Unmarshal(in []byte, body interface{}) error {
return json.Unmarshal(in, body)

Check warning on line 55 in restful/serialize_jsonpb.go

View check run for this annotation

Codecov / codecov/patch

restful/serialize_jsonpb.go#L54-L55

Added lines #L54 - L55 were not covered by tests
}

// Marshal returns the serialized bytes in json protocol.
func (StandardJSONSerializer) Marshal(body interface{}) ([]byte, error) {
return json.Marshal(body)

Check warning on line 60 in restful/serialize_jsonpb.go

View check run for this annotation

Codecov / codecov/patch

restful/serialize_jsonpb.go#L59-L60

Added lines #L59 - L60 were not covered by tests
}

// MarshalIndent is like Marshal but applies Indent to format the output.
// Each JSON element in the output will begin on a new line beginning with prefix
// followed by one or more copies of indent according to the indentation nesting.
func (StandardJSONSerializer) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
return json.MarshalIndent(v, prefix, indent)

Check warning on line 67 in restful/serialize_jsonpb.go

View check run for this annotation

Codecov / codecov/patch

restful/serialize_jsonpb.go#L66-L67

Added lines #L66 - L67 were not covered by tests
}

// Marshaller is a configurable protojson marshaler.
var Marshaller = protojson.MarshalOptions{EmitUnpopulated: true}
Expand Down Expand Up @@ -104,15 +132,15 @@ func marshalNonProtoField(v interface{}) ([]byte, error) {
// marshal map proto message
if rv.Kind() == reflect.Map {
// make map for marshalling
m := make(map[string]*jsoniter.RawMessage)
m := make(map[string]*json.RawMessage)
for _, key := range rv.MapKeys() { // range all keys
// marshal value
out, err := marshal(rv.MapIndex(key).Interface())
if err != nil {
return out, err
}
// assignment
m[fmt.Sprintf("%v", key.Interface())] = (*jsoniter.RawMessage)(&out)
m[fmt.Sprintf("%v", key.Interface())] = (*json.RawMessage)(&out)
if Marshaller.Indent != "" { // 指定 indent
return JSONAPI.MarshalIndent(v, "", Marshaller.Indent)
}
Expand Down Expand Up @@ -193,7 +221,7 @@ func unmarshalNonProtoField(data []byte, v interface{}) error {
// can only unmarshal numeric enum
if _, ok := rv.Interface().(wrappedEnum); ok {
var x interface{}
if err := jsoniter.Unmarshal(data, &x); err != nil {
if err := json.Unmarshal(data, &x); err != nil {
return err
}
switch t := x.(type) {
Expand All @@ -206,8 +234,8 @@ func unmarshalNonProtoField(data []byte, v interface{}) error {
}
// unmarshal to slice
if rv.Kind() == reflect.Slice {
// unmarshal to jsoniter.RawMessage first
var rms []jsoniter.RawMessage
// unmarshal to json.RawMessage first
var rms []json.RawMessage
if err := JSONAPI.Unmarshal(data, &rms); err != nil {
return err
}
Expand All @@ -229,8 +257,8 @@ func unmarshalNonProtoField(data []byte, v interface{}) error {
if rv.IsNil() { // rv MakeMap
rv.Set(reflect.MakeMap(rv.Type()))
}
// unmarshal to map[string]*jsoniter.RawMessage first
m := make(map[string]*jsoniter.RawMessage)
// unmarshal to map[string]*json.RawMessage first
m := make(map[string]*json.RawMessage)
if err := JSONAPI.Unmarshal(data, &m); err != nil {
return err
}
Expand All @@ -242,7 +270,7 @@ func unmarshalNonProtoField(data []byte, v interface{}) error {
}
// unmarshal value
if value == nil {
rm := jsoniter.RawMessage("null")
rm := json.RawMessage("null")
value = &rm
}
rn := reflect.New(rv.Type().Elem())
Expand Down

0 comments on commit 26b9e07

Please sign in to comment.