add cnf/json parse() and get() + minimal tests
This commit is contained in:
parent
05e6b5a847
commit
ad7c79d2f9
|
@ -0,0 +1,54 @@
|
|||
package cnf
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Json struct {
|
||||
data interface{}
|
||||
parsed bool
|
||||
}
|
||||
|
||||
// Parse extract a reader as its JSON representation
|
||||
func (d *Json) Parse(_reader io.Reader) error {
|
||||
|
||||
// 1. get json decoder
|
||||
decoder := json.NewDecoder(_reader)
|
||||
err := decoder.Decode(&d.data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.parsed = true
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// Get returns the value of a dot-separated path, and if it exists
|
||||
func (d *Json) Get(_path string) (string, bool) {
|
||||
|
||||
// 1. extract path
|
||||
path := strings.Split(_path, ".")
|
||||
|
||||
// 2. Iterate over path / nested fields
|
||||
current := d.data
|
||||
for _, field := range path {
|
||||
fmap, ok := current.(map[string]interface{})
|
||||
if !ok { // incomplete path
|
||||
return "", false
|
||||
}
|
||||
|
||||
child, ok := fmap[field]
|
||||
if !ok { // incomplete path
|
||||
return "", false
|
||||
}
|
||||
|
||||
current = child
|
||||
}
|
||||
|
||||
// 3. Only return if string value
|
||||
value, ok := current.(string)
|
||||
return value, ok
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package cnf
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSimpleJson(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
raw string
|
||||
key string
|
||||
}{
|
||||
{`{ "key": "value" }`, "key"},
|
||||
{`{ "ignore": "xxx", "key": "value" }`, "key"},
|
||||
{`{ "parent": { "child": "value" } }`, "parent.child"},
|
||||
{`{ "ignore": "xxx", "parent": { "child": "value" } }`, "parent.child"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
parser := new(Json)
|
||||
reader := bytes.NewBufferString(test.raw)
|
||||
|
||||
// try to extract value
|
||||
err := parser.Parse(reader)
|
||||
if err != nil {
|
||||
t.Errorf("parse error: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// extract value
|
||||
value, found := parser.Get(test.key)
|
||||
if !found {
|
||||
t.Errorf("expected a result, got none")
|
||||
continue
|
||||
}
|
||||
|
||||
// check value
|
||||
if value != "value" {
|
||||
t.Errorf("expected 'value' got '%s'", value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestNotString(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
raw string
|
||||
key string
|
||||
}{
|
||||
{`{ "key": ["value"] }`, "key"},
|
||||
{`{ "key": {"subkey": "value"} }`, "key"},
|
||||
{`{ "parent": { "child": [ "value" ] } }`, "parent.child"},
|
||||
{`{ "parent": { "child": { "subkey": "value" } } }`, "parent.child"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
parser := new(Json)
|
||||
reader := bytes.NewBufferString(test.raw)
|
||||
|
||||
// try to extract value
|
||||
err := parser.Parse(reader)
|
||||
if err != nil {
|
||||
t.Errorf("parse error: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// extract value
|
||||
value, found := parser.Get(test.key)
|
||||
if found || len(value) > 0 {
|
||||
t.Errorf("expected no result, got '%s'", value)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue