Add test cases for MarshalJSON and MarshalText

This commit is contained in:
Masaaki Goshima 2020-08-19 00:32:45 +09:00
parent 4232d1d16d
commit 1d2beb8473
7 changed files with 1355 additions and 391 deletions

View File

@ -171,7 +171,7 @@ func (t opType) fieldToOmitEmptyField() opType {
primitiveTypes := []string{
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64",
"float32", "float64", "bool", "string",
"float32", "float64", "bool", "string", "MarshalJSON", "MarshalText",
}
primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes {
@ -181,8 +181,6 @@ func (t opType) fieldToOmitEmptyField() opType {
{"End", "EndIndent", "Op"},
{"Interface", "InterfaceIndent", "Op"},
{"Ptr", "PtrIndent", "Op"},
{"MarshalJSON", "MarshalJSONIndent", "Op"},
{"MarshalText", "MarshalTextIndent", "Op"},
{"SliceHead", "SliceHeadIndent", "SliceHead"},
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
{"SliceElem", "SliceElemIndent", "SliceElem"},

View File

@ -8,6 +8,7 @@ import (
)
func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) {
root := true
switch {
case typ.Implements(marshalJSONType):
return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil
@ -18,12 +19,15 @@ func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) {
case rtype_ptrTo(typ).Implements(marshalTextType):
return newOpCode(opMarshalText, rtype_ptrTo(typ), e.indent, newEndOp(e.indent)), nil
}
isPtr := false
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
isPtr = true
}
root := true
if typ.Kind() == reflect.Map {
return e.compileMap(typ, false, root, withIndent)
return e.compileMap(typ, isPtr, root, withIndent)
} else if typ.Kind() == reflect.Struct {
return e.compileStruct(typ, isPtr, root, withIndent)
}
return e.compile(typ, root, withIndent)
}
@ -49,7 +53,7 @@ func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) {
case reflect.Map:
return e.compileMap(typ, true, root, withIndent)
case reflect.Struct:
return e.compileStruct(typ, root, withIndent)
return e.compileStruct(typ, false, root, withIndent)
case reflect.Interface:
return e.compileInterface(typ, root)
case reflect.Int:
@ -376,6 +380,10 @@ func (e *Encoder) typeToHeaderType(op opType) opType {
return opStructFieldHeadString
case opBool:
return opStructFieldHeadBool
case opMarshalJSON:
return opStructFieldHeadMarshalJSON
case opMarshalText:
return opStructFieldHeadMarshalText
}
return opStructFieldHead
}
@ -410,6 +418,10 @@ func (e *Encoder) typeToFieldType(op opType) opType {
return opStructFieldString
case opBool:
return opStructFieldBool
case opMarshalJSON:
return opStructFieldMarshalJSON
case opMarshalText:
return opStructFieldMarshalText
}
return opStructField
}
@ -505,7 +517,7 @@ func (e *Encoder) structField(fieldCode *structFieldCode, valueCode *opcode, isO
}
return code
}
func (e *Encoder) compileStruct(typ *rtype, root, withIndent bool) (*opcode, error) {
func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opcode, error) {
if code := e.compiledCode(typ, withIndent); code != nil {
return code, nil
}
@ -534,6 +546,15 @@ func (e *Encoder) compileStruct(typ *rtype, root, withIndent bool) (*opcode, err
}
keyName, isOmitEmpty := e.keyNameAndOmitEmptyFromField(field)
fieldType := type2rtype(field.Type)
if isPtr && i == 0 {
// head field of pointer structure at top level
// if field type is pointer and implements MarshalJSON or MarshalText,
// it need to operation of dereference of pointer.
if field.Type.Kind() == reflect.Ptr &&
(field.Type.Implements(marshalJSONType) || field.Type.Implements(marshalTextType)) {
fieldType = rtype_ptrTo(fieldType)
}
}
valueCode, err := e.compile(fieldType, false, withIndent)
if err != nil {
return nil, err
@ -554,7 +575,7 @@ func (e *Encoder) compileStruct(typ *rtype, root, withIndent bool) (*opcode, err
key := fmt.Sprintf(`"%s":`, keyName)
fieldCode := &structFieldCode{
opcodeHeader: &opcodeHeader{
typ: fieldType,
typ: valueCode.typ,
next: valueCode,
indent: e.indent,
},

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@ package json_test
import (
"errors"
"fmt"
"reflect"
"testing"
"time"
@ -491,6 +492,108 @@ func Test_MarshalIndent(t *testing.T) {
})
}
func TestMarshalRawMessageValue(t *testing.T) {
type (
T1 struct {
M json.RawMessage `json:",omitempty"`
}
T2 struct {
M *json.RawMessage `json:",omitempty"`
}
)
var (
rawNil = json.RawMessage(nil)
rawEmpty = json.RawMessage([]byte{})
rawText = json.RawMessage([]byte(`"foo"`))
)
tests := []struct {
in interface{}
want string
ok bool
}{
// Test with nil RawMessage.
{rawNil, "null", true},
{&rawNil, "null", true},
{[]interface{}{rawNil}, "[null]", true},
{&[]interface{}{rawNil}, "[null]", true},
{[]interface{}{&rawNil}, "[null]", true},
{&[]interface{}{&rawNil}, "[null]", true},
{struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true},
{&struct{ M json.RawMessage }{rawNil}, `{"M":null}`, true},
{struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true},
{&struct{ M *json.RawMessage }{&rawNil}, `{"M":null}`, true},
{map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
{&map[string]interface{}{"M": rawNil}, `{"M":null}`, true},
{map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
{&map[string]interface{}{"M": &rawNil}, `{"M":null}`, true},
{T1{rawNil}, "{}", true},
{T2{&rawNil}, `{"M":null}`, true},
{&T1{rawNil}, "{}", true},
{&T2{&rawNil}, `{"M":null}`, true},
// Test with empty, but non-nil, RawMessage.
{rawEmpty, "", false},
{&rawEmpty, "", false},
{[]interface{}{rawEmpty}, "", false},
{&[]interface{}{rawEmpty}, "", false},
{[]interface{}{&rawEmpty}, "", false},
{&[]interface{}{&rawEmpty}, "", false},
{struct{ X json.RawMessage }{rawEmpty}, "", false},
{&struct{ X json.RawMessage }{rawEmpty}, "", false},
{struct{ X *json.RawMessage }{&rawEmpty}, "", false},
{&struct{ X *json.RawMessage }{&rawEmpty}, "", false},
{map[string]interface{}{"nil": rawEmpty}, "", false},
{&map[string]interface{}{"nil": rawEmpty}, "", false},
{map[string]interface{}{"nil": &rawEmpty}, "", false},
{&map[string]interface{}{"nil": &rawEmpty}, "", false},
{T1{rawEmpty}, "{}", true},
{T2{&rawEmpty}, "", false},
{&T1{rawEmpty}, "{}", true},
{&T2{&rawEmpty}, "", false},
// Test with RawMessage with some text.
//
// The tests below marked with Issue6458 used to generate "ImZvbyI=" instead "foo".
// This behavior was intentionally changed in Go 1.8.
// See https://golang.org/issues/14493#issuecomment-255857318
{rawText, `"foo"`, true}, // Issue6458
{&rawText, `"foo"`, true},
{[]interface{}{rawText}, `["foo"]`, true}, // Issue6458
{&[]interface{}{rawText}, `["foo"]`, true}, // Issue6458
{[]interface{}{&rawText}, `["foo"]`, true},
{&[]interface{}{&rawText}, `["foo"]`, true},
{struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true}, // Issue6458
{&struct{ M json.RawMessage }{rawText}, `{"M":"foo"}`, true},
{struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true},
{&struct{ M *json.RawMessage }{&rawText}, `{"M":"foo"}`, true},
{map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
{&map[string]interface{}{"M": rawText}, `{"M":"foo"}`, true}, // Issue6458
{map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
{&map[string]interface{}{"M": &rawText}, `{"M":"foo"}`, true},
{T1{rawText}, `{"M":"foo"}`, true}, // Issue6458
{T2{&rawText}, `{"M":"foo"}`, true},
{&T1{rawText}, `{"M":"foo"}`, true},
{&T2{&rawText}, `{"M":"foo"}`, true},
}
for i, tt := range tests {
b, err := json.Marshal(tt.in)
if ok := (err == nil); ok != tt.ok {
if err != nil {
t.Errorf("test %d, unexpected failure: %v", i, err)
} else {
t.Errorf("test %d, unexpected success", i)
}
}
if got := string(b); got != tt.want {
t.Errorf("test %d, Marshal(%#v) = %q, want %q", i, tt.in, got, tt.want)
}
}
}
type marshalerError struct{}
func (*marshalerError) MarshalJSON() ([]byte, error) {
@ -607,3 +710,59 @@ func TestMarshalerEscaping(t *testing.T) {
t.Errorf("Marshal(ct) = %#q, want %#q", got, want)
}
}
type marshalPanic struct{}
func (marshalPanic) MarshalJSON() ([]byte, error) { panic(0xdead) }
func TestMarshalPanic(t *testing.T) {
defer func() {
if got := recover(); !reflect.DeepEqual(got, 0xdead) {
t.Errorf("panic() = (%T)(%v), want 0xdead", got, got)
}
}()
json.Marshal(&marshalPanic{})
t.Error("Marshal should have panicked")
}
func TestMarshalUncommonFieldNames(t *testing.T) {
v := struct {
A0, À, int
}{}
b, err := json.Marshal(v)
if err != nil {
t.Fatal("Marshal:", err)
}
want := `{"A0":0,"À":0,"Aβ":0}`
got := string(b)
if got != want {
t.Fatalf("Marshal: got %s want %s", got, want)
}
}
func TestMarshalerError(t *testing.T) {
s := "test variable"
st := reflect.TypeOf(s)
errText := "json: test error"
tests := []struct {
err *json.MarshalerError
want string
}{
{
json.NewMarshalerError(st, fmt.Errorf(errText), ""),
"json: error calling MarshalJSON for type " + st.String() + ": " + errText,
},
{
json.NewMarshalerError(st, fmt.Errorf(errText), "TestMarshalerError"),
"json: error calling TestMarshalerError for type " + st.String() + ": " + errText,
},
}
for i, tt := range tests {
got := tt.err.Error()
if got != tt.want {
t.Errorf("MarshalerError test %d, got: %s, want: %s", i, got, tt.want)
}
}
}

View File

@ -3,6 +3,7 @@ package json
import (
"bytes"
"encoding"
"fmt"
"math"
"reflect"
"strconv"
@ -115,6 +116,12 @@ func (e *Encoder) run(code *opcode) error {
Err: err,
}
}
if len(b) == 0 {
return errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
0,
)
}
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
@ -933,6 +940,131 @@ func (e *Encoder) run(code *opcode) error {
field.nextField.ptr = ptr
code = field.next
}
case opStructFieldPtrHeadMarshalJSON:
code.ptr = e.ptrToPtr(code.ptr)
fallthrough
case opStructFieldHeadMarshalJSON:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
e.encodeNull()
code = field.end
} else {
e.encodeByte('{')
e.encodeBytes(field.key)
fmt.Println("code.typ = ", code.typ)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
if len(b) == 0 {
return errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
0,
)
}
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(buf.Bytes())
field.nextField.ptr = ptr
code = field.next
}
case opStructFieldPtrAnonymousHeadMarshalJSON:
code.ptr = e.ptrToPtr(code.ptr)
fallthrough
case opStructFieldAnonymousHeadMarshalJSON:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end
} else {
e.encodeBytes(field.key)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
if len(b) == 0 {
return errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
0,
)
}
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(buf.Bytes())
field.nextField.ptr = ptr
code = field.next
}
case opStructFieldPtrHeadMarshalText:
code.ptr = e.ptrToPtr(code.ptr)
fallthrough
case opStructFieldHeadMarshalText:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
e.encodeNull()
code = field.end
} else {
e.encodeByte('{')
e.encodeBytes(field.key)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
field.nextField.ptr = ptr
code = field.next
}
case opStructFieldPtrAnonymousHeadMarshalText:
code.ptr = e.ptrToPtr(code.ptr)
fallthrough
case opStructFieldAnonymousHeadMarshalText:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end
} else {
e.encodeBytes(field.key)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
field.nextField.ptr = ptr
code = field.next
}
case opStructFieldPtrHeadIndent:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -1912,6 +2044,159 @@ func (e *Encoder) run(code *opcode) error {
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyMarshalJSON:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldHeadOmitEmptyMarshalJSON:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
e.encodeNull()
code = field.end.next
} else {
e.encodeByte('{')
p := unsafe.Pointer(ptr + field.offset)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = field.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
if len(b) == 0 {
if isPtr {
return errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
0,
)
}
code = field.nextField
} else {
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(field.key)
e.encodeBytes(buf.Bytes())
code = field.next
}
}
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyMarshalJSON:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyMarshalJSON:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
p := unsafe.Pointer(ptr + field.offset)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = field.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
if len(b) == 0 {
if isPtr {
return errUnexpectedEndOfJSON(
fmt.Sprintf("error calling MarshalJSON for type %s", code.typ),
0,
)
}
code = field.nextField
} else {
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(field.key)
e.encodeBytes(buf.Bytes())
code = field.next
}
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyMarshalText:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldHeadOmitEmptyMarshalText:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
e.encodeNull()
code = field.end.next
} else {
e.encodeByte('{')
p := unsafe.Pointer(ptr + field.offset)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = field.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeBytes(field.key)
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrAnonymousHeadOmitEmptyMarshalText:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyMarshalText:
field := code.toStructFieldCode()
ptr := field.ptr
if ptr == 0 {
code = field.end.next
} else {
p := unsafe.Pointer(ptr + field.offset)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = field.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeBytes(field.key)
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
code = field.next
}
field.nextField.ptr = ptr
}
case opStructFieldPtrHeadOmitEmptyIndent:
if code.ptr != 0 {
code.ptr = e.ptrToPtr(code.ptr)
@ -2465,7 +2750,52 @@ func (e *Encoder) run(code *opcode) error {
e.encodeBytes(c.key)
e.encodeBool(e.ptrToBool(c.ptr + c.offset))
code = code.next
case opStructFieldMarshalJSON:
if e.buf[len(e.buf)-1] != '{' {
e.encodeByte(',')
}
c := code.toStructFieldCode()
c.nextField.ptr = c.ptr
e.encodeBytes(c.key)
ptr := c.ptr + c.offset
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(buf.Bytes())
code = code.next
case opStructFieldMarshalText:
if e.buf[len(e.buf)-1] != '{' {
e.encodeByte(',')
}
c := code.toStructFieldCode()
c.nextField.ptr = c.ptr
e.encodeBytes(c.key)
ptr := c.ptr + c.offset
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
code = code.next
case opStructFieldIndent:
c := code.toStructFieldCode()
if e.buf[len(e.buf)-2] != '{' {
@ -2827,6 +3157,52 @@ func (e *Encoder) run(code *opcode) error {
code = code.next
code.ptr = c.ptr
case opStructFieldOmitEmptyMarshalJSON:
c := code.toStructFieldCode()
ptr := c.ptr + c.offset
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
if v != nil {
b, err := v.(Marshaler).MarshalJSON()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
var buf bytes.Buffer
if err := compact(&buf, b, true); err != nil {
return err
}
e.encodeBytes(buf.Bytes())
}
code = code.next
code.ptr = c.ptr
case opStructFieldOmitEmptyMarshalText:
c := code.toStructFieldCode()
ptr := c.ptr + c.offset
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
if v != nil {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: code.typ,
ptr: unsafe.Pointer(ptr),
}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
e.encodeString(*(*string)(unsafe.Pointer(&bytes)))
}
code = code.next
code.ptr = c.ptr
case opStructFieldOmitEmptyIndent:
c := code.toStructFieldCode()
p := c.ptr + c.offset

View File

@ -123,7 +123,7 @@ func errNotAtBeginningOfValue(cursor int64) *SyntaxError {
func errUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf("unexpected end of JSON input for %s", msg),
msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg),
Offset: cursor,
}
}

View File

@ -1,8 +1,18 @@
package json
import "reflect"
func NewSyntaxError(msg string, offset int64) *SyntaxError {
return &SyntaxError{
msg: msg,
Offset: offset,
}
}
func NewMarshalerError(typ reflect.Type, err error, msg string) *MarshalerError {
return &MarshalerError{
Type: typ,
Err: err,
sourceFunc: msg,
}
}