You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	consolidate marshaler tests
This commit is contained in:
		| @@ -1,152 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
| 	jsoniter "github.com/json-iterator/go" | ||||
| ) | ||||
|  | ||||
| func Test_Roundtrip(t *testing.T) { | ||||
| 	fz := fuzz.New().MaxDepth(10).NilChance(0.3) | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		var before typeForTest | ||||
| 		fz.Fuzz(&before) | ||||
|  | ||||
| 		jbStd, err := json.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with stdlib: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbStd))) == 0 { | ||||
| 			t.Fatal("stdlib marshal produced empty result and no error") | ||||
| 		} | ||||
| 		jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with jsoniter: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbIter))) == 0 { | ||||
| 			t.Fatal("jsoniter marshal produced empty result and no error") | ||||
| 		} | ||||
| 		if string(jbStd) != string(jbIter) { | ||||
| 			t.Fatalf("marshal expected:\n    %s\ngot:\n    %s\nobj:\n    %s", | ||||
| 				indent(jbStd, "    "), indent(jbIter, "    "), dump(before)) | ||||
| 		} | ||||
|  | ||||
| 		var afterStd typeForTest | ||||
| 		err = json.Unmarshal(jbIter, &afterStd) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		var afterIter typeForTest | ||||
| 		err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		if fingerprint(afterStd) != fingerprint(afterIter) { | ||||
| 			t.Fatalf("unmarshal expected:\n    %s\ngot:\n    %s\nvia:\n    %s", | ||||
| 				dump(afterStd), dump(afterIter), indent(jbIter, "    ")) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const indentStr = ">  " | ||||
|  | ||||
| func fingerprint(obj interface{}) string { | ||||
| 	c := spew.ConfigState{ | ||||
| 		SortKeys: true, | ||||
| 		SpewKeys: true, | ||||
| 	} | ||||
| 	return c.Sprintf("%v", obj) | ||||
| } | ||||
|  | ||||
| func dump(obj interface{}) string { | ||||
| 	cfg := spew.ConfigState{ | ||||
| 		Indent: indentStr, | ||||
| 	} | ||||
| 	return cfg.Sdump(obj) | ||||
| } | ||||
|  | ||||
| func indent(src []byte, prefix string) string { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := json.Indent(&buf, src, prefix, indentStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("!!! %v", err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var obj typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&obj) | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		jb, err := fn(obj) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to marshal:\n input: %s\n  error: %v", name, dump(obj), err) | ||||
| 		} | ||||
| 		_ = jb | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var before typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&before) | ||||
| 	jb, err := json.Marshal(before) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to marshal: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		var after typeForTest | ||||
| 		err = fn(jb, &after) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to unmarshal:\n  input: %q\n  error: %v", name, string(jb), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardMarshal(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "stdlib", json.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardUnmarshal(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "stdlib", json.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalFastest(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalDefault(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalCompatible(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) | ||||
| } | ||||
| @@ -1,50 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type marshalerForTest string | ||||
|  | ||||
| func encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m marshalerForTest) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + encode(string(m)) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *marshalerForTest) UnmarshalJSON(text []byte) error { | ||||
| 	*m = marshalerForTest(decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__"))) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = *new(marshalerForTest) | ||||
| var _ json.Unmarshaler = new(marshalerForTest) | ||||
|  | ||||
| type typeForTest marshalerForTest | ||||
| @@ -1,152 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
| 	jsoniter "github.com/json-iterator/go" | ||||
| ) | ||||
|  | ||||
| func Test_Roundtrip(t *testing.T) { | ||||
| 	fz := fuzz.New().MaxDepth(10).NilChance(0.3) | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		var before typeForTest | ||||
| 		fz.Fuzz(&before) | ||||
|  | ||||
| 		jbStd, err := json.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with stdlib: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbStd))) == 0 { | ||||
| 			t.Fatal("stdlib marshal produced empty result and no error") | ||||
| 		} | ||||
| 		jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with jsoniter: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbIter))) == 0 { | ||||
| 			t.Fatal("jsoniter marshal produced empty result and no error") | ||||
| 		} | ||||
| 		if string(jbStd) != string(jbIter) { | ||||
| 			t.Fatalf("marshal expected:\n    %s\ngot:\n    %s\nobj:\n    %s", | ||||
| 				indent(jbStd, "    "), indent(jbIter, "    "), dump(before)) | ||||
| 		} | ||||
|  | ||||
| 		var afterStd typeForTest | ||||
| 		err = json.Unmarshal(jbIter, &afterStd) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		var afterIter typeForTest | ||||
| 		err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		if fingerprint(afterStd) != fingerprint(afterIter) { | ||||
| 			t.Fatalf("unmarshal expected:\n    %s\ngot:\n    %s\nvia:\n    %s", | ||||
| 				dump(afterStd), dump(afterIter), indent(jbIter, "    ")) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const indentStr = ">  " | ||||
|  | ||||
| func fingerprint(obj interface{}) string { | ||||
| 	c := spew.ConfigState{ | ||||
| 		SortKeys: true, | ||||
| 		SpewKeys: true, | ||||
| 	} | ||||
| 	return c.Sprintf("%v", obj) | ||||
| } | ||||
|  | ||||
| func dump(obj interface{}) string { | ||||
| 	cfg := spew.ConfigState{ | ||||
| 		Indent: indentStr, | ||||
| 	} | ||||
| 	return cfg.Sdump(obj) | ||||
| } | ||||
|  | ||||
| func indent(src []byte, prefix string) string { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := json.Indent(&buf, src, prefix, indentStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("!!! %v", err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var obj typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&obj) | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		jb, err := fn(obj) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to marshal:\n input: %s\n  error: %v", name, dump(obj), err) | ||||
| 		} | ||||
| 		_ = jb | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var before typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&before) | ||||
| 	jb, err := json.Marshal(before) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to marshal: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		var after typeForTest | ||||
| 		err = fn(jb, &after) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to unmarshal:\n  input: %q\n  error: %v", name, string(jb), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardMarshal(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "stdlib", json.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardUnmarshal(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "stdlib", json.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalFastest(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalDefault(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalCompatible(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type marshalerForTest struct { | ||||
| 	X string | ||||
| } | ||||
|  | ||||
| func encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m marshalerForTest) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + encode(m.X) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *marshalerForTest) UnmarshalJSON(text []byte) error { | ||||
| 	m.X = decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__")) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = marshalerForTest{} | ||||
| var _ json.Unmarshaler = &marshalerForTest{} | ||||
|  | ||||
| type typeForTest marshalerForTest | ||||
| @@ -1,152 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
| 	jsoniter "github.com/json-iterator/go" | ||||
| ) | ||||
|  | ||||
| func Test_Roundtrip(t *testing.T) { | ||||
| 	fz := fuzz.New().MaxDepth(10).NilChance(0.3) | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		var before typeForTest | ||||
| 		fz.Fuzz(&before) | ||||
|  | ||||
| 		jbStd, err := json.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with stdlib: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbStd))) == 0 { | ||||
| 			t.Fatal("stdlib marshal produced empty result and no error") | ||||
| 		} | ||||
| 		jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with jsoniter: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbIter))) == 0 { | ||||
| 			t.Fatal("jsoniter marshal produced empty result and no error") | ||||
| 		} | ||||
| 		if string(jbStd) != string(jbIter) { | ||||
| 			t.Fatalf("marshal expected:\n    %s\ngot:\n    %s\nobj:\n    %s", | ||||
| 				indent(jbStd, "    "), indent(jbIter, "    "), dump(before)) | ||||
| 		} | ||||
|  | ||||
| 		var afterStd typeForTest | ||||
| 		err = json.Unmarshal(jbIter, &afterStd) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		var afterIter typeForTest | ||||
| 		err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		if fingerprint(afterStd) != fingerprint(afterIter) { | ||||
| 			t.Fatalf("unmarshal expected:\n    %s\ngot:\n    %s\nvia:\n    %s", | ||||
| 				dump(afterStd), dump(afterIter), indent(jbIter, "    ")) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const indentStr = ">  " | ||||
|  | ||||
| func fingerprint(obj interface{}) string { | ||||
| 	c := spew.ConfigState{ | ||||
| 		SortKeys: true, | ||||
| 		SpewKeys: true, | ||||
| 	} | ||||
| 	return c.Sprintf("%v", obj) | ||||
| } | ||||
|  | ||||
| func dump(obj interface{}) string { | ||||
| 	cfg := spew.ConfigState{ | ||||
| 		Indent: indentStr, | ||||
| 	} | ||||
| 	return cfg.Sdump(obj) | ||||
| } | ||||
|  | ||||
| func indent(src []byte, prefix string) string { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := json.Indent(&buf, src, prefix, indentStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("!!! %v", err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var obj typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&obj) | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		jb, err := fn(obj) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to marshal:\n input: %s\n  error: %v", name, dump(obj), err) | ||||
| 		} | ||||
| 		_ = jb | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var before typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&before) | ||||
| 	jb, err := json.Marshal(before) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to marshal: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		var after typeForTest | ||||
| 		err = fn(jb, &after) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to unmarshal:\n  input: %q\n  error: %v", name, string(jb), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardMarshal(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "stdlib", json.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardUnmarshal(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "stdlib", json.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalFastest(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalDefault(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalCompatible(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) | ||||
| } | ||||
| @@ -1,54 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type marshalerForTest struct { | ||||
| 	X string | ||||
| } | ||||
|  | ||||
| func encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m marshalerForTest) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + encode(m.X) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *marshalerForTest) UnmarshalJSON(text []byte) error { | ||||
| 	m.X = decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__")) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = marshalerForTest{} | ||||
| var _ json.Unmarshaler = &marshalerForTest{} | ||||
|  | ||||
| type typeA marshalerForTest | ||||
|  | ||||
| type typeForTest typeA | ||||
| @@ -1,152 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
| 	jsoniter "github.com/json-iterator/go" | ||||
| ) | ||||
|  | ||||
| func Test_Roundtrip(t *testing.T) { | ||||
| 	fz := fuzz.New().MaxDepth(10).NilChance(0.3) | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		var before typeForTest | ||||
| 		fz.Fuzz(&before) | ||||
|  | ||||
| 		jbStd, err := json.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with stdlib: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbStd))) == 0 { | ||||
| 			t.Fatal("stdlib marshal produced empty result and no error") | ||||
| 		} | ||||
| 		jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with jsoniter: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbIter))) == 0 { | ||||
| 			t.Fatal("jsoniter marshal produced empty result and no error") | ||||
| 		} | ||||
| 		if string(jbStd) != string(jbIter) { | ||||
| 			t.Fatalf("marshal expected:\n    %s\ngot:\n    %s\nobj:\n    %s", | ||||
| 				indent(jbStd, "    "), indent(jbIter, "    "), dump(before)) | ||||
| 		} | ||||
|  | ||||
| 		var afterStd typeForTest | ||||
| 		err = json.Unmarshal(jbIter, &afterStd) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		var afterIter typeForTest | ||||
| 		err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		if fingerprint(afterStd) != fingerprint(afterIter) { | ||||
| 			t.Fatalf("unmarshal expected:\n    %s\ngot:\n    %s\nvia:\n    %s", | ||||
| 				dump(afterStd), dump(afterIter), indent(jbIter, "    ")) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const indentStr = ">  " | ||||
|  | ||||
| func fingerprint(obj interface{}) string { | ||||
| 	c := spew.ConfigState{ | ||||
| 		SortKeys: true, | ||||
| 		SpewKeys: true, | ||||
| 	} | ||||
| 	return c.Sprintf("%v", obj) | ||||
| } | ||||
|  | ||||
| func dump(obj interface{}) string { | ||||
| 	cfg := spew.ConfigState{ | ||||
| 		Indent: indentStr, | ||||
| 	} | ||||
| 	return cfg.Sdump(obj) | ||||
| } | ||||
|  | ||||
| func indent(src []byte, prefix string) string { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := json.Indent(&buf, src, prefix, indentStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("!!! %v", err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var obj typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&obj) | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		jb, err := fn(obj) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to marshal:\n input: %s\n  error: %v", name, dump(obj), err) | ||||
| 		} | ||||
| 		_ = jb | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var before typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&before) | ||||
| 	jb, err := json.Marshal(before) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to marshal: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		var after typeForTest | ||||
| 		err = fn(jb, &after) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to unmarshal:\n  input: %q\n  error: %v", name, string(jb), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardMarshal(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "stdlib", json.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardUnmarshal(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "stdlib", json.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalFastest(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalDefault(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalCompatible(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) | ||||
| } | ||||
| @@ -1,56 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type marshalerForTest struct { | ||||
| 	X string | ||||
| } | ||||
|  | ||||
| func encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m marshalerForTest) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + encode(m.X) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *marshalerForTest) UnmarshalJSON(text []byte) error { | ||||
| 	m.X = decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__")) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = marshalerForTest{} | ||||
| var _ json.Unmarshaler = &marshalerForTest{} | ||||
|  | ||||
| type typeForTest struct { | ||||
| 	S string | ||||
| 	M marshalerForTest | ||||
| 	I int8 | ||||
| } | ||||
| @@ -1,152 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/davecgh/go-spew/spew" | ||||
| 	fuzz "github.com/google/gofuzz" | ||||
| 	jsoniter "github.com/json-iterator/go" | ||||
| ) | ||||
|  | ||||
| func Test_Roundtrip(t *testing.T) { | ||||
| 	fz := fuzz.New().MaxDepth(10).NilChance(0.3) | ||||
| 	for i := 0; i < 100; i++ { | ||||
| 		var before typeForTest | ||||
| 		fz.Fuzz(&before) | ||||
|  | ||||
| 		jbStd, err := json.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with stdlib: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbStd))) == 0 { | ||||
| 			t.Fatal("stdlib marshal produced empty result and no error") | ||||
| 		} | ||||
| 		jbIter, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(before) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to marshal with jsoniter: %v", err) | ||||
| 		} | ||||
| 		if len(strings.TrimSpace(string(jbIter))) == 0 { | ||||
| 			t.Fatal("jsoniter marshal produced empty result and no error") | ||||
| 		} | ||||
| 		if string(jbStd) != string(jbIter) { | ||||
| 			t.Fatalf("marshal expected:\n    %s\ngot:\n    %s\nobj:\n    %s", | ||||
| 				indent(jbStd, "    "), indent(jbIter, "    "), dump(before)) | ||||
| 		} | ||||
|  | ||||
| 		var afterStd typeForTest | ||||
| 		err = json.Unmarshal(jbIter, &afterStd) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with stdlib: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		var afterIter typeForTest | ||||
| 		err = jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal(jbIter, &afterIter) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("failed to unmarshal with jsoniter: %v\nvia:\n    %s", | ||||
| 				err, indent(jbIter, "    ")) | ||||
| 		} | ||||
| 		if fingerprint(afterStd) != fingerprint(afterIter) { | ||||
| 			t.Fatalf("unmarshal expected:\n    %s\ngot:\n    %s\nvia:\n    %s", | ||||
| 				dump(afterStd), dump(afterIter), indent(jbIter, "    ")) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| const indentStr = ">  " | ||||
|  | ||||
| func fingerprint(obj interface{}) string { | ||||
| 	c := spew.ConfigState{ | ||||
| 		SortKeys: true, | ||||
| 		SpewKeys: true, | ||||
| 	} | ||||
| 	return c.Sprintf("%v", obj) | ||||
| } | ||||
|  | ||||
| func dump(obj interface{}) string { | ||||
| 	cfg := spew.ConfigState{ | ||||
| 		Indent: indentStr, | ||||
| 	} | ||||
| 	return cfg.Sdump(obj) | ||||
| } | ||||
|  | ||||
| func indent(src []byte, prefix string) string { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := json.Indent(&buf, src, prefix, indentStr) | ||||
| 	if err != nil { | ||||
| 		return fmt.Sprintf("!!! %v", err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func benchmarkMarshal(t *testing.B, name string, fn func(interface{}) ([]byte, error)) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var obj typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&obj) | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		jb, err := fn(obj) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to marshal:\n input: %s\n  error: %v", name, dump(obj), err) | ||||
| 		} | ||||
| 		_ = jb | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func benchmarkUnmarshal(t *testing.B, name string, fn func(data []byte, v interface{}) error) { | ||||
| 	t.ReportAllocs() | ||||
| 	t.ResetTimer() | ||||
|  | ||||
| 	var before typeForTest | ||||
| 	fz := fuzz.NewWithSeed(0).MaxDepth(10).NilChance(0.3) | ||||
| 	fz.Fuzz(&before) | ||||
| 	jb, err := json.Marshal(before) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("failed to marshal: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < t.N; i++ { | ||||
| 		var after typeForTest | ||||
| 		err = fn(jb, &after) | ||||
| 		if err != nil { | ||||
| 			t.Fatalf("%s failed to unmarshal:\n  input: %q\n  error: %v", name, string(jb), err) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardMarshal(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "stdlib", json.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkStandardUnmarshal(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "stdlib", json.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalFastest(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalFastest(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-fastest", jsoniter.ConfigFastest.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalDefault(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-default", jsoniter.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalDefault(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-default", jsoniter.Unmarshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterMarshalCompatible(t *testing.B) { | ||||
| 	benchmarkMarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Marshal) | ||||
| } | ||||
|  | ||||
| func BenchmarkJSONIterUnmarshalCompatible(t *testing.B) { | ||||
| 	benchmarkUnmarshal(t, "jsoniter-compat", jsoniter.ConfigCompatibleWithStandardLibrary.Unmarshal) | ||||
| } | ||||
| @@ -1,58 +0,0 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type marshalerForTest struct { | ||||
| 	X string | ||||
| } | ||||
|  | ||||
| func encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m marshalerForTest) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + encode(m.X) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *marshalerForTest) UnmarshalJSON(text []byte) error { | ||||
| 	m.X = decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__")) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = marshalerForTest{} | ||||
| var _ json.Unmarshaler = &marshalerForTest{} | ||||
|  | ||||
| type typeA marshalerForTest | ||||
|  | ||||
| type typeForTest struct { | ||||
| 	S string | ||||
| 	M typeA | ||||
| 	I int8 | ||||
| } | ||||
							
								
								
									
										52
									
								
								type_tests/marshaler_string_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								type_tests/marshaler_string_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/base64" | ||||
| 	"strings" | ||||
| 	"encoding/json" | ||||
| ) | ||||
|  | ||||
| type stringMarshaler string | ||||
|  | ||||
| func (m stringMarshaler) encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func (m stringMarshaler) decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m stringMarshaler) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + m.encode(string(m)) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *stringMarshaler) UnmarshalJSON(text []byte) error { | ||||
| 	*m = stringMarshaler(m.decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__"))) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = *new(stringMarshaler) | ||||
| var _ json.Unmarshaler = new(stringMarshaler) | ||||
|  | ||||
| func init() { | ||||
| 	testCases = append(testCases, (*stringMarshaler)(nil)) | ||||
| } | ||||
							
								
								
									
										69
									
								
								type_tests/marshaler_struct_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								type_tests/marshaler_struct_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| package test | ||||
|  | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"encoding/base64" | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| ) | ||||
|  | ||||
| type structMarshaler struct { | ||||
| 	X string | ||||
| } | ||||
|  | ||||
| func (m structMarshaler) encode(str string) string { | ||||
| 	buf := bytes.Buffer{} | ||||
| 	b64 := base64.NewEncoder(base64.StdEncoding, &buf) | ||||
| 	if _, err := b64.Write([]byte(str)); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	if err := b64.Close(); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return buf.String() | ||||
| } | ||||
|  | ||||
| func (m structMarshaler) decode(str string) string { | ||||
| 	if len(str) == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	b64 := base64.NewDecoder(base64.StdEncoding, strings.NewReader(str)) | ||||
| 	bs := make([]byte, len(str)) | ||||
| 	if n, err := b64.Read(bs); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		bs = bs[:n] | ||||
| 	} | ||||
| 	return string(bs) | ||||
| } | ||||
|  | ||||
| func (m structMarshaler) MarshalJSON() ([]byte, error) { | ||||
| 	return []byte(`"MANUAL__` + m.encode(m.X) + `"`), nil | ||||
| } | ||||
|  | ||||
| func (m *structMarshaler) UnmarshalJSON(text []byte) error { | ||||
| 	m.X = m.decode(strings.TrimPrefix(strings.Trim(string(text), `"`), "MANUAL__")) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = structMarshaler{} | ||||
| var _ json.Unmarshaler = &structMarshaler{} | ||||
|  | ||||
| type structMarshalerAlias structMarshaler | ||||
|  | ||||
| func init() { | ||||
| 	testCases = append(testCases, | ||||
| 		(*structMarshaler)(nil), | ||||
| 		(*structMarshalerAlias)(nil), | ||||
| 		(*struct { | ||||
| 			S string | ||||
| 			M structMarshaler | ||||
| 			I int8 | ||||
| 		})(nil), | ||||
| 		(*struct { | ||||
| 			S string | ||||
| 			M structMarshalerAlias | ||||
| 			I int8 | ||||
| 		})(nil), | ||||
| 	) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user