From b8bb8e5f8eb6ae928f08698df222d4e5e2b74c2d Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 25 Apr 2020 11:01:02 +0200 Subject: pkg/serializer: support primitive user types in interfaces Add 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)". --- pkg/serializer/serializer.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'pkg/serializer/serializer.go') 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") -- cgit mrf-deployment