Skip to content

Instantly share code, notes, and snippets.

@rodkranz
Last active May 18, 2018 09:30
Show Gist options
  • Save rodkranz/2327141978d6284c770bca6f3a757ca1 to your computer and use it in GitHub Desktop.
Save rodkranz/2327141978d6284c770bca6f3a757ca1 to your computer and use it in GitHub Desktop.
Simple Nested in GO
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