save the edited JSON

develop
skanehira 5 years ago
parent baa39d60f5
commit 483c604c64

@ -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
}

@ -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)
})

@ -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]
}
Loading…
Cancel
Save