Last active
May 18, 2018 09:30
-
-
Save rodkranz/2327141978d6284c770bca6f3a757ca1 to your computer and use it in GitHub Desktop.
Simple Nested in GO
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 characters
package main | |
import ( | |
"testing" | |
"fmt" | |
"reflect" | |
"strings" | |
) | |
// Implementation Nested | |
func Nested(position string, mapper map[string]interface{}) (interface{}, bool) { | |
pos := strings.Split(position, ".") | |
t := mapper | |
for key, posKey := range pos { | |
v, ok := t[posKey] | |
if !ok { | |
return nil, false | |
} | |
if newValue, ok := v.(map[string]interface{}); ok { | |
if key+1 == len(pos) { | |
return v, true | |
} | |
t = newValue | |
} else if newString, ok := v.(string); ok { | |
return newString, true | |
} else if newInt, ok := v.(int); ok { | |
return newInt, true | |
} | |
} | |
return nil, false | |
} | |
func NestedString(position string, mapper map[string]interface{}) (value string, ok bool) { | |
var valueTmp interface{} | |
if valueTmp, ok = Nested(position, mapper); !ok { | |
return "", false | |
} | |
if value, ok = valueTmp.(string); !ok { | |
return "", false | |
} | |
return value, true | |
} | |
func NestedInt(position string, mapper map[string]interface{}) (value int, ok bool) { | |
var valueTmp interface{} | |
if valueTmp, ok = Nested(position, mapper); !ok { | |
return 0, false | |
} | |
if value, ok = valueTmp.(int); !ok { | |
return 0, false | |
} | |
return value, true | |
} | |
func NestedTime(position string, mapper map[string]interface{}, layout string) (value time.Time, ok bool) { | |
var valueTmp string | |
if valueTmp, ok = NestedString(position, mapper); !ok { | |
return time.Time{}, false | |
} | |
if layout == "" { | |
layout = time.RFC3339 | |
} | |
var err error | |
if value, err = time.Parse(layout, valueTmp); err != nil { | |
return time.Time{}, false | |
} | |
return value, true | |
} | |
// Test for Nested function | |
func TestNested(t *testing.T) { | |
data := map[string]interface{}{ | |
"advert": map[string]interface{}{ | |
"id": "12", | |
"title": "Lorem Ipsum", | |
"status": map[string]interface{}{ | |
"code": "active", | |
"url": "www.loremipsum.com", | |
"ttl": 123123, | |
}, | |
"contact": map[string]interface{}{ | |
"name": "daniel3", | |
"phones": []string{ | |
"790123123", | |
"790123546", | |
}, | |
}, | |
}, | |
} | |
tests := []struct { | |
Parameter string | |
ExpectedFirst interface{} | |
ExpectedSecond bool | |
Data map[string]interface{} | |
}{ | |
{ | |
Parameter: "advert.id", | |
ExpectedFirst: "12", | |
ExpectedSecond: true, | |
Data: data, | |
}, | |
{ | |
Parameter: "advert.status.code", | |
ExpectedFirst: "active", | |
ExpectedSecond: true, | |
Data: data, | |
}, | |
{ | |
Parameter: "advert.status.ttl", | |
ExpectedFirst: 123123, | |
ExpectedSecond: true, | |
Data: data, | |
}, | |
{ | |
Parameter: "advert.contact", | |
ExpectedFirst: map[string]interface{}{ | |
"name": "daniel3", | |
"phones": []string{ | |
"790123123", | |
"790123546", | |
}, | |
}, | |
ExpectedSecond: true, | |
Data: data, | |
}, | |
{ | |
Parameter: "advert.bananas", | |
ExpectedFirst: nil, | |
ExpectedSecond: false, | |
Data: data, | |
}, | |
} | |
for key, test := range tests { | |
t.Run(fmt.Sprintf("Test #%d", key), func(t *testing.T) { | |
actual, result := Nested(test.Parameter, test.Data) | |
if !reflect.DeepEqual(test.ExpectedFirst, actual) || result != test.ExpectedSecond { | |
t.Errorf("[%d] expected param1: %T(%v) and param2: %T(%v), but got param1: %T(%v) and param2: %T(%v)", | |
key, | |
test.ExpectedFirst, test.ExpectedFirst, // param1 | |
test.ExpectedSecond, test.ExpectedSecond, // param2 | |
actual, actual, // actual | |
result, result, // result | |
) | |
} | |
}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment