Skip to content

Commit

Permalink
Add ability to customize internal json marshaler
Browse files Browse the repository at this point in the history
Added a package level variable "InterfaceMarshalFunc".
It's used to marshal interface to JSON encoded byte slice,
mostly when event.Interface("key", v) is called.
  • Loading branch information
povsister committed May 20, 2021
1 parent 3c3b4a3 commit aecc284
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 5 deletions.
7 changes: 7 additions & 0 deletions encoder_cbor.go
Expand Up @@ -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)
}
Expand Down
7 changes: 7 additions & 0 deletions encoder_json.go
Expand Up @@ -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...)
}
Expand Down
5 changes: 5 additions & 0 deletions globals.go
@@ -1,6 +1,7 @@
package zerolog

import (
"encoding/json"
"strconv"
"sync/atomic"
"time"
Expand Down Expand Up @@ -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.
Expand Down
10 changes: 9 additions & 1 deletion 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
Expand All @@ -8,4 +16,4 @@ func (e Encoder) AppendKey(dst []byte, key string) []byte {
dst = e.AppendBeginMarker(dst)
}
return e.AppendString(dst, key)
}
}
3 changes: 1 addition & 2 deletions internal/cbor/types.go
@@ -1,7 +1,6 @@
package cbor

import (
"encoding/json"
"fmt"
"math"
"net"
Expand Down Expand Up @@ -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))
}
Expand Down
8 changes: 8 additions & 0 deletions 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.
Expand Down
3 changes: 1 addition & 2 deletions internal/json/types.go
@@ -1,7 +1,6 @@
package json

import (
"encoding/json"
"fmt"
"math"
"net"
Expand Down Expand Up @@ -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))
}
Expand Down

0 comments on commit aecc284

Please sign in to comment.