From ad7c79d2f9be93f62851d5725bc81fc1ce1a8f57 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Wed, 7 Nov 2018 14:03:54 +0100 Subject: [PATCH] add cnf/json parse() and get() + minimal tests --- internal/cnf/json.go | 54 ++++++++++++++++++++++++++ internal/cnf/json_test.go | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 internal/cnf/json.go create mode 100644 internal/cnf/json_test.go diff --git a/internal/cnf/json.go b/internal/cnf/json.go new file mode 100644 index 0000000..c65ba86 --- /dev/null +++ b/internal/cnf/json.go @@ -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 +} diff --git a/internal/cnf/json_test.go b/internal/cnf/json_test.go new file mode 100644 index 0000000..5ce828c --- /dev/null +++ b/internal/cnf/json_test.go @@ -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 + } + + } + +}