diff --git a/encoder_cbor.go b/encoder_cbor.go index f8d3fe9..7b0dafe 100644 --- a/encoder_cbor.go +++ b/encoder_cbor.go @@ -14,6 +14,13 @@ var ( enc = cbor.Encoder{} ) +func init() { + // using closure to reflect the changes at runtime. + cbor.JSONMarshalFunc = func(v interface{}) ([]byte, error) { + return InterfaceMarshalFunc(v) + } +} + func appendJSON(dst []byte, j []byte) []byte { return cbor.AppendEmbeddedJSON(dst, j) } diff --git a/encoder_json.go b/encoder_json.go index fe580f5..0e0450e 100644 --- a/encoder_json.go +++ b/encoder_json.go @@ -15,6 +15,13 @@ var ( enc = json.Encoder{} ) +func init() { + // using closure to reflect the changes at runtime. + json.JSONMarshalFunc = func(v interface{}) ([]byte, error) { + return InterfaceMarshalFunc(v) + } +} + func appendJSON(dst []byte, j []byte) []byte { return append(dst, j...) } diff --git a/globals.go b/globals.go index 2c60382..98c67ed 100644 --- a/globals.go +++ b/globals.go @@ -1,6 +1,7 @@ package zerolog import ( + "encoding/json" "strconv" "sync/atomic" "time" @@ -75,6 +76,10 @@ var ( return err } + // InterfaceMarshalFunc allows customization of interface marshaling. + // Default: "encoding/json.Marshal" + InterfaceMarshalFunc = json.Marshal + // TimeFieldFormat defines the time format of the Time field type. If set to // TimeFormatUnix, TimeFormatUnixMs or TimeFormatUnixMicro, the time is formatted as an UNIX // timestamp as integer. diff --git a/internal/cbor/base.go b/internal/cbor/base.go index 58cd082..51fe86c 100644 --- a/internal/cbor/base.go +++ b/internal/cbor/base.go @@ -1,5 +1,13 @@ package cbor +// JSONMarshalFunc is used to marshal interface to JSON encoded byte slice. +// Making it package level instead of embedded in Encoder brings +// some extra efforts at importing, but avoids value copy when the functions +// of Encoder being invoked. +// DO REMEMBER to set this variable at importing, or +// you might get a nil pointer dereference panic at runtime. +var JSONMarshalFunc func(v interface{}) ([]byte, error) + type Encoder struct{} // AppendKey adds a key (string) to the binary encoded log message @@ -8,4 +16,4 @@ func (e Encoder) AppendKey(dst []byte, key string) []byte { dst = e.AppendBeginMarker(dst) } return e.AppendString(dst, key) -} \ No newline at end of file +} diff --git a/internal/cbor/types.go b/internal/cbor/types.go index 3d76ea0..a41c797 100644 --- a/internal/cbor/types.go +++ b/internal/cbor/types.go @@ -1,7 +1,6 @@ package cbor import ( - "encoding/json" "fmt" "math" "net" @@ -432,7 +431,7 @@ func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte { // AppendInterface takes an arbitrary object and converts it to JSON and embeds it dst. func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte { - marshaled, err := json.Marshal(i) + marshaled, err := JSONMarshalFunc(i) if err != nil { return e.AppendString(dst, fmt.Sprintf("marshaling error: %v", err)) } diff --git a/internal/json/base.go b/internal/json/base.go index 62248e7..09ec59f 100644 --- a/internal/json/base.go +++ b/internal/json/base.go @@ -1,5 +1,13 @@ package json +// JSONMarshalFunc is used to marshal interface to JSON encoded byte slice. +// Making it package level instead of embedded in Encoder brings +// some extra efforts at importing, but avoids value copy when the functions +// of Encoder being invoked. +// DO REMEMBER to set this variable at importing, or +// you might get a nil pointer dereference panic at runtime. +var JSONMarshalFunc func(v interface{}) ([]byte, error) + type Encoder struct{} // AppendKey appends a new key to the output JSON. diff --git a/internal/json/types.go b/internal/json/types.go index 924416c..9e35266 100644 --- a/internal/json/types.go +++ b/internal/json/types.go @@ -1,7 +1,6 @@ package json import ( - "encoding/json" "fmt" "math" "net" @@ -363,7 +362,7 @@ func (Encoder) AppendFloats64(dst []byte, vals []float64) []byte { // AppendInterface marshals the input interface to a string and // appends the encoded string to the input byte slice. func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte { - marshaled, err := json.Marshal(i) + marshaled, err := JSONMarshalFunc(i) if err != nil { return e.AppendString(dst, fmt.Sprintf("marshaling error: %v", err)) }