diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-04-25 11:01:02 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-04-25 11:01:02 +0200 |
| commit | b8bb8e5f8eb6ae928f08698df222d4e5e2b74c2d (patch) | |
| tree | afc4f3b920efb87e5029f2b6fdeb385ae729bb72 /pkg/serializer/serializer.go | |
| parent | b3cb1996a4f40025f58ea785f1e555d851e10149 (diff) | |
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)".
Diffstat (limited to 'pkg/serializer/serializer.go')
| -rw-r--r-- | pkg/serializer/serializer.go | 30 |
1 files changed, 25 insertions, 5 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") |
