Skip to content

Commit

Permalink
Fix field marshaller (#73)
Browse files Browse the repository at this point in the history
  • Loading branch information
instabledesign authored Mar 12, 2020
1 parent 79fd0af commit b4f500c
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 15 deletions.
18 changes: 17 additions & 1 deletion field.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package logger

import (
"encoding/json"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -106,6 +107,22 @@ func (f *Field) String() string {
}
}

// MarshalJSON was called by json.Marshal(field)
// json Marshaller interface
func (f *Field) MarshalJSON() ([]byte, error) {
if marshallable, ok := f.Value.(json.Marshaler); ok {
return marshallable.MarshalJSON()
}
switch f.Type {
case BoolType, Int8Type, Int16Type, Int32Type, Int64Type, Uint8Type, Uint16Type, Uint32Type, Uint64Type, UintptrType, Float32Type, Float64Type:
return []byte(f.String()), nil
case SkipType, Complex64Type, Complex128Type, StringType, BinaryType, ByteStringType, ErrorType, TimeType, DurationType, StringerType:
return strconv.AppendQuote([]byte{}, f.String()), nil
default:
return json.Marshal(f.Value)
}
}

// GoString was called by fmt.Printf("%#v", Fields)
// fmt GoStringer interface
func (f *Field) GoString() string {
Expand All @@ -118,7 +135,6 @@ func (f *Field) GoString() string {
builder.WriteString(strconv.FormatUint(uint64(f.Type), 10))
builder.WriteString("}")
return builder.String()

}

// Skip will create Skip Field
Expand Down
67 changes: 56 additions & 11 deletions field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestField(t *testing.T) {
{field: logger.ByteString("ByteString field", []byte("my_value")), expectedValue: []byte("my_value"), expectedType: logger.ByteStringType},
{field: logger.Error("Error field", err), expectedValue: err, expectedType: logger.ErrorType},
{field: logger.Time("Time field", now), expectedValue: now, expectedType: logger.TimeType},
{field: logger.Duration("Duration field", 5 * time.Second), expectedValue: 5 * time.Second, expectedType: logger.DurationType},
{field: logger.Duration("Duration field", 5*time.Second), expectedValue: 5 * time.Second, expectedType: logger.DurationType},
{field: logger.Stringer("Stringer field", MyStringer{}), expectedValue: MyStringer{}, expectedType: logger.StringerType},
{field: logger.Reflect("Reflect field", struct{}{}), expectedValue: struct{}{}, expectedType: logger.ReflectType},
}
Expand All @@ -64,9 +64,9 @@ func TestField(t *testing.T) {

func TestField_Any(t *testing.T) {
tests := []struct {
name string
value interface{}
expectedType logger.FieldType
name string
value interface{}
expectedType logger.FieldType
}{
{name: "my bool", value: true, expectedType: logger.BoolType},
{name: "my bool", value: false, expectedType: logger.BoolType},
Expand Down Expand Up @@ -124,14 +124,14 @@ func TestField_String(t *testing.T) {
{field: logger.Uintptr("Uintptr field", 123), expectedString: "123"},
{field: logger.Float32("Float32 field", 1.23456789), expectedString: "1.234567881"},
{field: logger.Float64("Float64 field", 123.4567891011), expectedString: "123.4567891"},
{field: logger.Complex64("Complex64 field", 6 + 7i), expectedString: "(6+7i)"},
{field: logger.Complex128("Complex128 field", 6 + 7i), expectedString: "(6+7i)"},
{field: logger.Complex64("Complex64 field", 6+7i), expectedString: "(6+7i)"},
{field: logger.Complex128("Complex128 field", 6+7i), expectedString: "(6+7i)"},
{field: logger.String("String field", "my_value"), expectedString: "my_value"},
{field: logger.Binary("Binary field", []byte{1, 2, 3}), expectedString: "\x01\x02\x03"},
{field: logger.ByteString("ByteString field", []byte("my_value")), expectedString: "my_value"},
{field: logger.Error("Error field", err), expectedString: "my_error_value"},
{field: logger.Time("Time field", now), expectedString: now.String()},
{field: logger.Duration("Duration field", 5 * time.Second), expectedString: "5s"},
{field: logger.Duration("Duration field", 5*time.Second), expectedString: "5s"},
{field: logger.Stringer("Stringer field", MyStringer{}), expectedString: "my_stringer"},
{field: logger.Reflect("Reflect field", struct{}{}), expectedString: "{}"},
}
Expand All @@ -143,6 +143,51 @@ func TestField_String(t *testing.T) {
}
}

func TestField_MarshalJSON(t *testing.T) {
now := time.Now()
nowMarshalled, _ := now.MarshalJSON()
err := errors.New("my_error_value")

tests := []struct {
name string
field logger.Field
expectedString string
}{
{field: logger.Skip("Skip field", "my_value"), expectedString: `"<skipped>"`},
{field: logger.Bool("Bool field", true), expectedString: "true"},
{field: logger.Bool("Bool field", false), expectedString: "false"},
{field: logger.Int8("Int8 field", 123), expectedString: "123"},
{field: logger.Int16("Int16 field", 123), expectedString: "123"},
{field: logger.Int32("Int32 field", 123), expectedString: "123"},
{field: logger.Int64("Int64 field", 123), expectedString: "123"},
{field: logger.Uint8("Uint8 field", 123), expectedString: "123"},
{field: logger.Uint16("Uint16 field", 123), expectedString: "123"},
{field: logger.Uint32("Uint32 field", 123), expectedString: "123"},
{field: logger.Uint64("Uint64 field", 123), expectedString: "123"},
{field: logger.Uintptr("Uintptr field", 123), expectedString: "123"},
{field: logger.Float32("Float32 field", 1.23456789), expectedString: "1.234567881"},
{field: logger.Float64("Float64 field", 123.4567891011), expectedString: "123.4567891"},
{field: logger.Complex64("Complex64 field", 6+7i), expectedString: `"(6+7i)"`},
{field: logger.Complex128("Complex128 field", 6+7i), expectedString: `"(6+7i)"`},
{field: logger.String("String field", "my_value"), expectedString: `"my_value"`},
{field: logger.Binary("Binary field", []byte{1, 2, 3}), expectedString: `"\x01\x02\x03"`},
{field: logger.ByteString("ByteString field", []byte("my_value")), expectedString: `"my_value"`},
{field: logger.Error("Error field", err), expectedString: `"my_error_value"`},
{field: logger.Time("Time field", now), expectedString: string(nowMarshalled)},
{field: logger.Duration("Duration field", 5*time.Second), expectedString: `"5s"`},
{field: logger.Stringer("Stringer field", MyStringer{}), expectedString: `"my_stringer"`},
{field: logger.Reflect("Reflect field", struct{}{}), expectedString: "{}"},
}

for _, tt := range tests {
t.Run(tt.field.Name, func(t *testing.T) {
result, err := tt.field.MarshalJSON()
assert.NoError(t, err)
assert.Equal(t, tt.expectedString, string(result))
})
}
}

func TestField_GoString(t *testing.T) {
now := time.Now()
error := errors.New("my_error_value")
Expand All @@ -166,14 +211,14 @@ func TestField_GoString(t *testing.T) {
{field: logger.Uintptr("Uintptr field", 123), expectedGoString: "logger.Field{Name: Uintptr field, Value: 123, Type: 11}"},
{field: logger.Float32("Float32 field", 1.23456789), expectedGoString: "logger.Field{Name: Float32 field, Value: 1.234567881, Type: 12}"},
{field: logger.Float64("Float64 field", 123.4567891011), expectedGoString: "logger.Field{Name: Float64 field, Value: 123.4567891, Type: 13}"},
{field: logger.Complex64("Complex64 field", 6 + 7i), expectedGoString: "logger.Field{Name: Complex64 field, Value: (6+7i), Type: 14}"},
{field: logger.Complex128("Complex128 field", 6 + 7i), expectedGoString: "logger.Field{Name: Complex128 field, Value: (6+7i), Type: 15}"},
{field: logger.Complex64("Complex64 field", 6+7i), expectedGoString: "logger.Field{Name: Complex64 field, Value: (6+7i), Type: 14}"},
{field: logger.Complex128("Complex128 field", 6+7i), expectedGoString: "logger.Field{Name: Complex128 field, Value: (6+7i), Type: 15}"},
{field: logger.String("String field", "my_value"), expectedGoString: "logger.Field{Name: String field, Value: my_value, Type: 16}"},
{field: logger.Binary("Binary field", []byte{1, 2, 3}), expectedGoString: "logger.Field{Name: Binary field, Value: \x01\x02\x03, Type: 17}"},
{field: logger.ByteString("ByteString field", []byte("my_value")), expectedGoString: "logger.Field{Name: ByteString field, Value: my_value, Type: 18}"},
{field: logger.Error("Error field", error), expectedGoString: "logger.Field{Name: Error field, Value: my_error_value, Type: 19}"},
{field: logger.Time("Time field", now), expectedGoString: "logger.Field{Name: Time field, Value: "+now.String()+", Type: 20}"},
{field: logger.Duration("Duration field", 5 * time.Second), expectedGoString: "logger.Field{Name: Duration field, Value: 5s, Type: 21}"},
{field: logger.Time("Time field", now), expectedGoString: "logger.Field{Name: Time field, Value: " + now.String() + ", Type: 20}"},
{field: logger.Duration("Duration field", 5*time.Second), expectedGoString: "logger.Field{Name: Duration field, Value: 5s, Type: 21}"},
{field: logger.Stringer("Stringer field", MyStringer{}), expectedGoString: "logger.Field{Name: Stringer field, Value: my_stringer, Type: 22}"},
{field: logger.Reflect("Reflect field", struct{}{}), expectedGoString: "logger.Field{Name: Reflect field, Value: {}, Type: 23}"},
}
Expand Down
5 changes: 2 additions & 3 deletions formatter/json.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package formatter

import (
"encoding/json"
"strconv"
"strings"

Expand Down Expand Up @@ -47,8 +46,8 @@ func ContextToJSON(context *logger.Context, builder *strings.Builder) {
builder.WriteRune('"')
builder.WriteString(name)
builder.WriteString("\":")
d, _ := json.Marshal(field.Value)
builder.WriteString(string(d))
d, _ := field.MarshalJSON()
builder.Write(d)
i++
}
builder.WriteString("}")
Expand Down
6 changes: 6 additions & 0 deletions formatter/json_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package formatter_test

import (
"errors"
"fmt"
"strings"
"testing"
Expand Down Expand Up @@ -65,6 +66,11 @@ func TestMarshalContextTo(t *testing.T) {
context: logger.NewContext().Add("my_key", time.Date(2020, 1, 2, 3, 4, 5, 6, time.UTC)),
expectedStrings: []string{`my_key":"2020-01-02T03:04:05.000000006Z"`},
},
{
name: "test time message with context",
context: logger.NewContext().Add("my_key", errors.New("my error message")),
expectedStrings: []string{`my_key":"my error message"`},
},
}

for _, tt := range tests {
Expand Down

0 comments on commit b4f500c

Please sign in to comment.