From 483c604c6489a4c1d9bdd62ecb25c87fd7be893d Mon Sep 17 00:00:00 2001 From: skanehira Date: Fri, 1 Nov 2019 16:41:49 +0900 Subject: [PATCH] save the edited JSON --- gui/gui.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++----- gui/tree.go | 50 ++++++++++++++++++++++++++++++++++--------- gui/type.go | 25 ++++++++++++++++++++++ 3 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 gui/type.go diff --git a/gui/gui.go b/gui/gui.go index af47d88..242bba7 100644 --- a/gui/gui.go +++ b/gui/gui.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "log" "os" + "strconv" "strings" "github.com/gdamore/tcell" @@ -165,18 +166,18 @@ func (g *Gui) SaveJSON() { fileName := form.GetFormItem(0).(*tview.InputField).GetText() fileName = os.ExpandEnv(fileName) - var b bytes.Buffer - enc := json.NewEncoder(&b) + var buf bytes.Buffer + enc := json.NewEncoder(&buf) enc.SetIndent("", " ") - if err := enc.Encode(g.Tree.OriginJSON); err != nil { - msg := fmt.Sprintf("can't make json: %s", err) + if err := enc.Encode(g.makeJSON(g.Tree.GetRoot())); err != nil { + msg := fmt.Sprintf("can't marshal json: %s", err) log.Println(msg) g.Message(msg, "main", func() {}) return } - if err := ioutil.WriteFile(fileName, b.Bytes(), 0666); err != nil { + if err := ioutil.WriteFile(fileName, buf.Bytes(), 0666); err != nil { msg := fmt.Sprintf("can't create file: %s", err) log.Println(msg) g.Message(msg, "main", func() {}) @@ -193,3 +194,53 @@ func (g *Gui) SaveJSON() { g.Pages.AddAndSwitchToPage(pageName, g.Modal(form, 0, 8), true).ShowPage("main") } + +func (g *Gui) makeJSON(node *tview.TreeNode) interface{} { + nodeType := node.GetReference().(Type) + children := node.GetChildren() + + switch nodeType { + case Root: + if len(children) == 1 { + return g.makeJSON(children[0]) + } else { + var i []interface{} + for _, n := range children { + i = append(i, g.makeJSON(n)) + } + return i + } + case Object: + i := make(map[string]interface{}) + for _, n := range children { + i[n.GetText()] = g.makeJSON(n) + } + return i + case Array: + var i []interface{} + for _, n := range children { + i = append(i, g.makeJSON(n)) + } + return i + case Key: + v := node.GetChildren()[0] + if v.GetReference().(Type) == Value { + return g.parseValue(v) + } + return map[string]interface{}{ + node.GetText(): g.makeJSON(v), + } + } + + return g.parseValue(node) +} + +func (g *Gui) parseValue(node *tview.TreeNode) interface{} { + v := node.GetText() + if i, err := strconv.Atoi(v); err == nil { + return i + } else if f, err := strconv.ParseFloat(v, 64); err == nil { + return f + } + return v +} diff --git a/gui/tree.go b/gui/tree.go index 98ce474..588d49c 100644 --- a/gui/tree.go +++ b/gui/tree.go @@ -2,6 +2,7 @@ package gui import ( "fmt" + "log" "reflect" "github.com/gdamore/tcell" @@ -11,7 +12,6 @@ import ( type Tree struct { *tview.TreeView OriginRoot *tview.TreeNode - OriginJSON interface{} } func NewTree() *Tree { @@ -25,11 +25,23 @@ func NewTree() *Tree { func (t *Tree) UpdateView(g *Gui, i interface{}) { g.App.QueueUpdateDraw(func() { - root := tview.NewTreeNode(".").SetChildren(t.AddNode(i)) + r := reflect.ValueOf(i) + + var root *tview.TreeNode + switch r.Kind() { + case reflect.Map: + root = tview.NewTreeNode("{object}").SetReference(Object) + case reflect.Slice: + root = tview.NewTreeNode("{array}").SetReference(Array) + default: + root = tview.NewTreeNode("{value}").SetReference(Key) + } + + root.SetChildren(t.AddNode(i)) t.SetRoot(root).SetCurrentNode(root) + originRoot := *root t.OriginRoot = &originRoot - t.OriginJSON = i }) } @@ -42,24 +54,38 @@ func (t *Tree) AddNode(node interface{}) []*tview.TreeNode { newNode := t.NewNodeWithLiteral(k). SetColor(tcell.ColorMediumSlateBlue). SetChildren(t.AddNode(v)) + r := reflect.ValueOf(v) + if r.Kind() == reflect.Slice { + newNode.SetReference(Array) + } else if r.Kind() == reflect.Map { + newNode.SetReference(Object) + } else { + newNode.SetReference(Key) + } + + log.Printf("key:%v value:%v value_kind:%v", k, v, newNode.GetReference()) nodes = append(nodes, newNode) } case []interface{}: - for i, v := range node { + for _, v := range node { switch n := v.(type) { - case map[string]interface{}, []interface{}: - if reflect.ValueOf(n).Len() > 0 { - numberNode := tview.NewTreeNode(fmt.Sprintf("[%d]", i+1)). - SetChildren(t.AddNode(v)) - nodes = append(nodes, numberNode) + case map[string]interface{}: + r := reflect.ValueOf(n) + if r.Kind() != reflect.Slice { + objectNode := tview.NewTreeNode("{object}"). + SetChildren(t.AddNode(v)).SetReference(Object) + + log.Printf("key:%v value:%v value_kind:%v", i, v, "object") + nodes = append(nodes, objectNode) } default: nodes = append(nodes, t.AddNode(v)...) } } default: - nodes = append(nodes, t.NewNodeWithLiteral(node)) + log.Printf("value:%v value_kind:%v", node, "value") + nodes = append(nodes, t.NewNodeWithLiteral(node).SetReference(Value)) } return nodes } @@ -70,6 +96,10 @@ func (t *Tree) NewNodeWithLiteral(i interface{}) *tview.TreeNode { func (t *Tree) SetKeybindings(g *Gui) { t.SetSelectedFunc(func(node *tview.TreeNode) { + nodeType := node.GetReference().(Type) + if nodeType == Root || nodeType == Object { + return + } g.Input(node.GetText(), "filed", func(text string) { node.SetText(text) }) diff --git a/gui/type.go b/gui/type.go new file mode 100644 index 0000000..138fb17 --- /dev/null +++ b/gui/type.go @@ -0,0 +1,25 @@ +package gui + +type Type int + +const ( + Unknown Type = iota + Root + Object + Array + Key + Value +) + +var TypeMap = map[Type]string{ + Unknown: "unknown", + Root: "root", + Object: "object", + Array: "array", + Key: "key", + Value: "value", +} + +func (t Type) String() string { + return TypeMap[t] +}