-
-
Save FZambia/9501653 to your computer and use it in GitHub Desktop.
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
// Example | |
package main; | |
import ( | |
"jsonhelper" | |
"fmt" | |
) | |
func main(){ | |
jsonValue := []interface {}{ | |
map[string]interface {}{"one" : map[string]interface{}{"two" : 1}}, | |
[]interface{}{"one", "two", "three"}, | |
map[string]interface {}{"one": []interface{}{1, 2 , 3}}, | |
} | |
value, err = getValue("/[2]/one[0]", jsonValue) | |
fmt.Println(value) // Output: 1 | |
} |
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 jsonhelper | |
import ( | |
"encoding/json" | |
"errors" | |
"fmt" | |
"reflect" | |
"strconv" | |
"strings" | |
"regexp" | |
) | |
var ( | |
itemMapRe = regexp.MustCompile("^[^0-9\\s\\[][^\\s\\[]*") | |
itemArrayRe = regexp.MustCompile("\\[[0-9]+\\]") | |
) | |
func LoadJson(jsonStr string) (interface{}, error) { | |
var jsonValue interface{} | |
err := json.Unmarshal([]byte(jsonStr), &jsonValue) | |
return jsonValue, err | |
} | |
func GetString(path string, jsonValue interface{}) (string, error) { | |
var result string | |
err := GetValue(path, jsonValue, &result) | |
return result, err | |
} | |
func GetInt(path string, jsonValue interface{}) (int, error) { | |
var result int | |
err := GetValue(path, jsonValue, &result) | |
return result, err | |
} | |
func GetFloat(path string, jsonValue interface{}) (float64, error) { | |
var result float64 | |
err := GetValue(path, jsonValue, &result) | |
return result, err | |
} | |
func GetSlice(path string, jsonValue interface {}) (result []interface{}, err error) { | |
err = GetValue(path, jsonValue, &result) | |
return | |
} | |
func GetMap(path string, jsonValue interface {}) (result map[string]interface {}, err error) { | |
err = GetValue(path, jsonValue, &result) | |
return | |
} | |
func GetValue(path string, jsonValue interface{}, result interface{}) error { | |
rv := reflect.ValueOf(result) | |
if rv.Kind() != reflect.Ptr || rv.IsNil() { | |
return errors.New(fmt.Sprintf("The value %#v is not a pointer, you must call GetValue with a pointer as an argument", result)) | |
} | |
value, err := getValue(path, jsonValue) | |
if err != nil { | |
return err | |
} | |
if reflect.TypeOf(result) != reflect.PtrTo(reflect.TypeOf(value)) { | |
return errors.New(fmt.Sprintf("The value %#v is not %v but %v", value, reflect.TypeOf(result).Elem(), reflect.TypeOf(value))) | |
} else { | |
valueReflect := reflect.ValueOf(value) | |
reflect.ValueOf(result).Elem().Set(valueReflect) | |
} | |
return nil | |
} | |
func getValue(path string, jsonValue interface{}) (interface {}, error) { | |
var found bool | |
currentJsonValue := jsonValue | |
for _, pathElement := range(strings.Split(path, "/")) { | |
itemMapName := itemMapRe.FindString(pathElement) | |
if itemMapName != "" { | |
if mapValue, ok := currentJsonValue.(map[string]interface{}); ok { | |
if currentJsonValue, found = mapValue[itemMapName]; !found { | |
return nil, errors.New(fmt.Sprintf("Could not find element in path. The errorneous element is %v", pathElement)) | |
} | |
} else { | |
return nil, errors.New(fmt.Sprintf("Could not find element in path. The errorneous element is %v", pathElement)) | |
} | |
} | |
arrayIndexes := itemArrayRe.FindAllString(pathElement, -1) | |
for _, indexStr := range(arrayIndexes) { | |
if arrayIndex, err := strconv.Atoi(indexStr[1:len(indexStr)-1]); err != nil { | |
return nil, errors.New(fmt.Sprintf("Array index '%v' should be an int type", pathElement)) | |
} else { | |
if arrayValue, ok := currentJsonValue.([]interface{}); ok { | |
if arrayIndex >= len(arrayValue) { | |
return nil, errors.New(fmt.Sprintf("Array index '%d' is out of range '%d'", arrayIndex, len(arrayValue))) | |
} | |
currentJsonValue = arrayValue[arrayIndex] | |
} else { | |
return nil, errors.New(fmt.Sprintf("Could not find element in path. The errorneous element is %v", pathElement)) | |
} | |
} | |
} | |
} | |
return currentJsonValue, nil | |
} |
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 jsonhelper | |
import ( | |
"testing" | |
"github.com/stretchr/testify/assert" | |
) | |
func TestGetValue(t *testing.T) { | |
jsonValue := map[string]interface{}{"one" : map[string]interface{}{"two" : 1}} | |
value, err := getValue("/one", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, map[string]interface{}{"two" : 1}) | |
} | |
value, err = getValue("/one/two", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, 1) | |
} | |
value, err = getValue("/one/two/three", jsonValue) | |
assert.NotNil(t, err) | |
} | |
func TestGetArrayValue(t *testing.T) { | |
jsonValue := []interface {}{ | |
map[string]interface {}{"one" : map[string]interface{}{"two" : 1}}, | |
[]interface{}{"one", "two", "three"}, | |
map[string]interface {}{"one": []interface{}{1, 2 , 3}}, | |
} | |
value, err := getValue("[0]/one", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, map[string]interface{}{"two" : 1}) | |
} | |
value, err = getValue("/[1][0]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "one") | |
} | |
value, err = getValue("/[1][2]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "three") | |
} | |
value, err = getValue("/[1][3]", jsonValue) | |
assert.NotNil(t, err) | |
value, err = getValue("/[2]/one[0]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, 1) | |
} | |
value, err = getValue("/[2]/two[0]", jsonValue) | |
assert.NotNil(t, err) | |
value, err = getValue("/one/one", jsonValue) | |
assert.NotNil(t, err) | |
value, err = getValue("/[]/one", jsonValue) | |
assert.NotNil(t, err) | |
} | |
func TestGet(t *testing.T) { | |
jsonValue := map[string]interface{}{ | |
"one" : map[string]interface{}{ "value" : "testString" }, | |
"two" : 2, | |
"three" : 1.1, | |
"four" : []int{1, 2}, | |
"five": []interface {}{"zero", 1, 2.2, []int{4, 5}}, | |
} | |
var value string | |
err := GetValue("/one/value", jsonValue, &value) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "testString") | |
} | |
err = GetValue("/five/[0]", jsonValue, &value) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "zero") | |
} | |
var valueInt int | |
err = GetValue("/two", jsonValue, &valueInt) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueInt, 2) | |
} | |
err = GetValue("/five[1]", jsonValue, &valueInt) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueInt, 1) | |
} | |
var valueFloat float64 | |
err = GetValue("/three", jsonValue, &valueFloat) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueFloat, 1.1) | |
} | |
err = GetValue("/five[2]", jsonValue, &valueFloat) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueFloat, 2.2) | |
} | |
var valueArray []int | |
err = GetValue("/four", jsonValue, &valueArray) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueArray, []int{1, 2}) | |
} | |
err = GetValue("/five[3]", jsonValue, &valueArray) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueArray, []int{4, 5}) | |
} | |
//passing value not pointer | |
err = GetValue("four", jsonValue, valueArray) | |
assert.NotNil(t, err) | |
} | |
func TestGetByType(t *testing.T) { | |
var ( | |
err error | |
) | |
jsonValue := map[string]interface{}{ | |
"one" : map[string]interface{}{ "value" : "testString" }, | |
"two" : 2, | |
"three" : 1.1, | |
"four" : []interface{} {1, 2}, | |
"five": []interface {}{"zero", 1, 2.2, []int{4, 5}}, | |
} | |
var value string | |
value, err = GetString("/one/value", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "testString") | |
} | |
value, err = GetString("/five/[0]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, value, "zero") | |
} | |
var valueInt int | |
valueInt, err = GetInt("/two", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueInt, 2) | |
} | |
valueInt, err = GetInt("/five[1]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueInt, 1) | |
} | |
var valueFloat float64 | |
valueFloat, err = GetFloat("/three", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueFloat, 1.1) | |
} | |
valueFloat, err = GetFloat("/five[2]", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueFloat, 2.2) | |
} | |
var valueSlice []interface{} | |
valueSlice, err = GetSlice("/four", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueSlice, []interface{}{1, 2}) | |
} | |
valueSlice, err = GetSlice("/five", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, len(valueSlice), 4) | |
assert.Equal(t, valueSlice[0], "zero") | |
} | |
var valueMap map[string]interface{} | |
valueMap, err = GetMap("/one", jsonValue) | |
if assert.Nil(t, err) { | |
assert.Equal(t, valueMap, map[string]interface{}{ "value" : "testString" }) | |
} | |
} | |
func TestLoadJson(t *testing.T) { | |
jsonValue, err := LoadJson("{\"uk\" : {\"one\": \"one\", \"two\": 2}}") | |
if assert.Nil(t, err) { | |
assert.Equal(t, jsonValue, map[string]interface {}{"uk":map[string]interface{}{"one":"one", "two":2}}) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment