aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/serializer/serializer.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2020-04-25 11:01:02 +0200
committerDmitry Vyukov <dvyukov@google.com>2020-04-25 11:01:02 +0200
commitb8bb8e5f8eb6ae928f08698df222d4e5e2b74c2d (patch)
treeafc4f3b920efb87e5029f2b6fdeb385ae729bb72 /pkg/serializer/serializer.go
parentb3cb1996a4f40025f58ea785f1e555d851e10149 (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.go30
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")