Last active
January 10, 2025 07:17
-
-
Save jsmouret/2bc876e8def6c63410556350eca3e43d to your computer and use it in GitHub Desktop.
Revisions
-
jsmouret revised this gist
Aug 3, 2017 . 1 changed file with 99 additions and 73 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,14 +1,19 @@ package pb import ( "fmt" "reflect" st "github.com/golang/protobuf/ptypes/struct" ) // ToStruct converts a map[string]interface{} to a ptypes.Struct func ToStruct(v map[string]interface{}) *st.Struct { size := len(v) if size == 0 { return nil } fields := make(map[string]*st.Value, size) for k, v := range v { fields[k] = ToValue(v) } @@ -19,12 +24,14 @@ func ToStruct(v map[string]interface{}) *st.Struct { // ToValue converts an interface{} to a ptypes.Value func ToValue(v interface{}) *st.Value { switch v := v.(type) { case nil: return nil case bool: return &st.Value{ Kind: &st.Value_BoolValue{ BoolValue: v, }, } case int: return &st.Value{ @@ -92,97 +99,116 @@ func ToValue(v interface{}) *st.Value { StringValue: v, }, } case error: return &st.Value{ Kind: &st.Value_StringValue{ StringValue: v.Error(), }, } default: // Fallback to reflection for other types return toValue(reflect.ValueOf(v)) } } func toValue(v reflect.Value) *st.Value { switch v.Kind() { case reflect.Bool: return &st.Value{ Kind: &st.Value_BoolValue{ BoolValue: v.Bool(), }, } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v.Int()), }, } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v.Uint()), }, } case reflect.Float32, reflect.Float64: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: v.Float(), }, } case reflect.Ptr: if v.IsNil() { return nil } return toValue(reflect.Indirect(v)) case reflect.Array, reflect.Slice: size := v.Len() if size == 0 { return nil } values := make([]*st.Value, size) for i := 0; i < size; i++ { values[i] = toValue(v.Index(i)) } return &st.Value{ Kind: &st.Value_ListValue{ ListValue: &st.ListValue{ Values: values, }, }, } case reflect.Struct: t := v.Type() size := v.NumField() if size == 0 { return nil } fields := make(map[string]*st.Value, size) for i := 0; i < size; i++ { name := t.Field(i).Name // Better way? if len(name) > 0 && 'A' <= name[0] && name[0] <= 'Z' { fields[name] = toValue(v.Field(i)) } } if len(fields) == 0 { return nil } return &st.Value{ Kind: &st.Value_StructValue{ StructValue: &st.Struct{ Fields: fields, }, }, } case reflect.Map: keys := v.MapKeys() if len(keys) == 0 { return nil } fields := make(map[string]*st.Value, len(keys)) for _, k := range keys { if k.Kind() == reflect.String { fields[k.String()] = toValue(v.MapIndex(k)) } } if len(fields) == 0 { return nil } return &st.Value{ Kind: &st.Value_StructValue{ StructValue: &st.Struct{ Fields: fields, }, }, } default: // Last resort return &st.Value{ Kind: &st.Value_StringValue{ StringValue: fmt.Sprint(v), }, } } } -
jsmouret revised this gist
Aug 3, 2017 . 1 changed file with 6 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -134,7 +134,8 @@ func ToValue(v interface{}) *st.Value { size := value.Len() values := make([]*st.Value, size) for i := 0; i < size; i++ { item := value.Index(i).Interface() values[i] = ToValue(item) } return &st.Value{ Kind: &st.Value_ListValue{ @@ -151,7 +152,8 @@ func ToValue(v interface{}) *st.Value { name := t.Field(i).Name // Better way? if len(name) > 0 && 'A' <= name[0] && name[0] <= 'Z' { item := value.Field(i).Interface() fields[name] = ToValue(item) } } return &st.Value{ @@ -166,7 +168,8 @@ func ToValue(v interface{}) *st.Value { fields := make(map[string]*st.Value, len(keys)) for _, k := range keys { if k.Kind() == reflect.String { item := value.MapIndex(k).Interface() fields[k.String()] = ToValue(item) } } return &st.Value{ -
jsmouret revised this gist
Aug 3, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -151,7 +151,7 @@ func ToValue(v interface{}) *st.Value { name := t.Field(i).Name // Better way? if len(name) > 0 && 'A' <= name[0] && name[0] <= 'Z' { fields[name] = ToValue(value.Field(i)) } } return &st.Value{ -
jsmouret created this gist
Aug 3, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,185 @@ package pb import ( "reflect" st "github.com/golang/protobuf/ptypes/struct" ) // ToStruct converts a map[string]interface{} to a ptypes.Struct func ToStruct(v map[string]interface{}) *st.Struct { fields := make(map[string]*st.Value, len(v)) for k, v := range v { fields[k] = ToValue(v) } return &st.Struct{ Fields: fields, } } // ToValue converts an interface{} to a ptypes.Value func ToValue(v interface{}) *st.Value { // Try common types first switch v := v.(type) { case nil: return &st.Value{ Kind: &st.Value_NullValue{}, } case int: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case int8: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case int32: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case int64: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case uint: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case uint8: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case uint32: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case uint64: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case float32: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: float64(v), }, } case float64: return &st.Value{ Kind: &st.Value_NumberValue{ NumberValue: v, }, } case string: return &st.Value{ Kind: &st.Value_StringValue{ StringValue: v, }, } case bool: return &st.Value{ Kind: &st.Value_BoolValue{ BoolValue: v, }, } case error: return &st.Value{ Kind: &st.Value_StringValue{ StringValue: v.Error(), }, } case map[string]string: fields := make(map[string]*st.Value, len(v)) for k, v := range v { fields[k] = &st.Value{ Kind: &st.Value_StringValue{ StringValue: v, }, } } return &st.Value{ Kind: &st.Value_StructValue{ StructValue: &st.Struct{ Fields: fields, }, }, } case map[string]interface{}: return &st.Value{ Kind: &st.Value_StructValue{ StructValue: ToStruct(v), }, } default: // Fallback to reflection for other types value := reflect.ValueOf(v) switch value.Kind() { case reflect.Array, reflect.Slice: size := value.Len() values := make([]*st.Value, size) for i := 0; i < size; i++ { values[i] = ToValue(value.Index(i)) } return &st.Value{ Kind: &st.Value_ListValue{ ListValue: &st.ListValue{ Values: values, }, }, } case reflect.Struct: t := value.Type() size := value.NumField() fields := make(map[string]*st.Value, size) for i := 0; i < size; i++ { name := t.Field(i).Name // Better way? if len(name) > 0 && 'A' <= name[0] && name[0] <= 'Z' { fields[t.Field(i).Name] = ToValue(value.Field(i)) } } return &st.Value{ Kind: &st.Value_StructValue{ StructValue: &st.Struct{ Fields: fields, }, }, } case reflect.Map: keys := value.MapKeys() fields := make(map[string]*st.Value, len(keys)) for _, k := range keys { if k.Kind() == reflect.String { fields[k.String()] = ToValue(value.MapIndex(k)) } } return &st.Value{ Kind: &st.Value_StructValue{ StructValue: &st.Struct{ Fields: fields, }, }, } default: return &st.Value{ Kind: &st.Value_NullValue{}, } } } }