Skip to content

json.RawMessage backwards compatibility #524

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,27 @@ package jsoniter
import (
"bytes"
"io"
"errors"
)

// RawMessage to make replace json with jsoniter
type RawMessage []byte

func (m RawMessage) MarshalJSON() ([]byte, error) {
if m == nil {
return []byte("null"), nil
}
return m, nil
}

func (m *RawMessage) UnmarshalJSON(data []byte) error {
if m == nil {
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
}
*m = append((*m)[0:0], data...)
return nil
}

// Unmarshal adapts to json/encoding Unmarshal API
//
// Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.
Expand Down
113 changes: 113 additions & 0 deletions misc_tests/jsoniter_raw_message_interop_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package misc_tests

import (
"encoding/json"
"fmt"
"github.com/json-iterator/go"
"testing"
)

type JsonTest struct {
Data json.RawMessage `json:"data"`
}

func (jt *JsonTest) Bytes() []byte {
return jt.Data
}

type JsonIterTest struct {
Data jsoniter.RawMessage `json:"data"`
}

func (jit *JsonIterTest) Bytes() []byte {
return jit.Data
}

func TestEncodingToAndFromJsonIter(t *testing.T) {
encodeTypes := map[string]encoderFunc{
"json": encodeJson,
"jsoniter": encodeJsonIter,
}

rawTypes := map[string]rawFunc{
"json": func() HasData { return &JsonTest{json.RawMessage("\"hello-world\"")} },
"jsoniter": func() HasData { return &JsonIterTest{jsoniter.RawMessage("\"hello-world\"")} },
}

decodeTypes := map[string]decoderFunc{
"json": decodeJson,
"jsoniter": decodeJsonIter,
}

var err error
for encoderType, encoder := range encodeTypes {
for encodeRawType, encodeRawFactory := range rawTypes {
for decodeType, decoder := range decodeTypes {
for decodeRawType, decodeRawFactory := range rawTypes {
desc := fmt.Sprintf("encoder:%s source:%s.RawMessage decoder:%s destination:%s.RawMessage\n",
encoderType, encodeRawType, decodeType, decodeRawType)

if err = runTest(encoder, encodeRawFactory, decoder, decodeRawFactory); err != nil {
t.Errorf("%s: %v", desc, err)
}
}
}
}
}
}

type encoderFunc func(interface{}) ([]byte, error)
type decoderFunc func([]byte, interface{}) error
type rawFunc func() HasData
type HasData interface {
Bytes() []byte
}

func encodeJson(raw interface{}) ([]byte, error) {
return json.Marshal(raw)
}

func encodeJsonIter(raw interface{}) ([]byte, error) {
return jsoniter.Marshal(raw)
}

func decodeJson(data []byte, raw interface{}) error {
return json.Unmarshal(data, &raw)
}

func decodeJsonIter(data []byte, raw interface{}) error {
return jsoniter.Unmarshal(data, &raw)
}

func runTest(encoder encoderFunc, encoderFactory rawFunc, decoder decoderFunc, decoderFactory rawFunc) error {
raw := encoderFactory()
data, err := encoder(raw)
if err != nil {
return fmt.Errorf("failed to encode: %v", err)
}

newRaw := decoderFactory()
if err = decoder(data, &newRaw); err != nil {
return fmt.Errorf("failed to decode %q: %v", string(data), err)
}

if !equals(raw.Bytes(), newRaw.Bytes()) {
return fmt.Errorf("%q != %q", string(raw.Bytes()), string(newRaw.Bytes()))
}

return nil
}

func equals(data1 []byte, data2 []byte) bool {
if len(data1) != len(data2) {
return false
}

for idx := 0; idx < len(data1); idx++ {
if data1[idx] != data2[idx] {
return false
}
}

return true
}