diff options
| -rw-r--r-- | pkg/serializer/serializer.go | 30 | ||||
| -rw-r--r-- | pkg/serializer/serializer_test.go | 12 |
2 files changed, 31 insertions, 11 deletions
diff --git a/pkg/serializer/serializer.go b/pkg/serializer/serializer.go index 4de4dc093..05c00a3bd 100644 --- a/pkg/serializer/serializer.go +++ b/pkg/serializer/serializer.go @@ -5,6 +5,7 @@ package serializer import ( "reflect" + "strings" "fmt" "io" @@ -35,11 +36,7 @@ func (w *writer) do(v reflect.Value, sliceElem bool) { case reflect.Ptr: w.doPtr(v, sliceElem) case reflect.Interface: - if v.IsNil() { - w.string("nil") - } else { - w.do(v.Elem(), false) - } + w.doInterface(v) case reflect.Slice: w.doSlice(v) case reflect.Struct: @@ -81,6 +78,29 @@ func (w *writer) doPtr(v reflect.Value, sliceElem bool) { w.do(v.Elem(), sliceElem) } +func (w *writer) doInterface(v reflect.Value) { + if v.IsNil() { + w.string("nil") + return + } + elem := v.Elem() + // Handling of user types that has underlying primitive types. Consider: + // type T int + // var obj interface{} = T(42) + // T has kind reflect.Int. But if we serialize obj as just "42", it will be turned into plain int. + // Detect this case and serialize obj as "T(42)". + if (elem.Kind() == reflect.Bool || elem.Kind() == reflect.String || + elem.Type().ConvertibleTo(reflect.TypeOf(0))) && + strings.Contains(elem.Type().String(), ".") { + w.string(elem.Type().Name()) + w.byte('(') + w.do(elem, false) + w.byte(')') + return + } + w.do(elem, false) +} + func (w *writer) doSlice(v reflect.Value) { if v.IsNil() || v.Len() == 0 { w.string("nil") diff --git a/pkg/serializer/serializer_test.go b/pkg/serializer/serializer_test.go index 63ed7aa71..e4efa6719 100644 --- a/pkg/serializer/serializer_test.go +++ b/pkg/serializer/serializer_test.go @@ -47,15 +47,15 @@ Y{}, nil, 0, 42, -0, -42, -96, -false, +T(0), +T(42), +U(96), false, +B(false), "", "foo", -"", -"foo", +S(""), +S("foo"), },nil}` buf := new(bytes.Buffer) Write(buf, x) |
