Skip to content

Commit 7bd739e

Browse files
authored
Merge pull request #13 from eiri/none-objects-array
Support parsing of none-object arrays
2 parents e971461 + d728da2 commit 7bd739e

File tree

4 files changed

+79
-31
lines changed

4 files changed

+79
-31
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ format: ## format code
3232

3333
.PHONY: run
3434
run: ## run for debug
35-
@cat $(PWD)/testdata/data.json | go run main.go columns_value.go
35+
@go run main.go columns_value.go -c seq,name,bool $(PWD)/testdata/data.json
3636
@echo
37-
@go run main.go columns_value.go -c seq,number,name -m $(PWD)/testdata/data.json
37+
@go run main.go columns_value.go $(PWD)/testdata/misc-array.json
3838
@echo
3939

4040
.PHONY: deps

main.go

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"gopkg.in/alecthomas/kingpin.v2"
99
"io"
1010
"os"
11-
"reflect"
1211
"sort"
1312
)
1413

@@ -93,50 +92,53 @@ func renderMarkdown(w io.Writer, header Header, rows Rows) {
9392
}
9493

9594
func parseJSON(r io.Reader) (header Header, rows Rows, err error) {
96-
var vv []interface{}
97-
var v interface{}
95+
var raw interface{}
9896
d := json.NewDecoder(r)
9997
d.UseNumber()
100-
err = d.Decode(&v)
98+
err = d.Decode(&raw)
10199
if err != nil {
102100
return
103101
}
104-
switch v := v.(type) {
102+
var records []interface{}
103+
switch rec := raw.(type) {
105104
case []interface{}:
106-
header = makeHeader(v[0])
107-
vv = v
105+
records = rec
108106
case map[string]interface{}:
109-
header = makeHeader(v)
110-
vv = append(vv, v)
107+
records = append(records, rec)
111108
default:
112109
err = errors.New("Unsupported JSON data structure")
113110
return
114111
}
115-
if len(header) == 0 {
116-
err = errors.New("Can't find specified column(s)")
117-
return
118-
}
119112

120-
for _, v := range vv {
121-
// we just skip none-object rows for now
122-
if v, ok := v.(map[string]interface{}); ok {
123-
var row []string
124-
for _, key := range header {
125-
val := fmt.Sprintf("%v", v[key])
126-
row = append(row, val)
113+
tableble := true
114+
for _, val := range records {
115+
var rec map[string]interface{}
116+
if r, ok := val.(map[string]interface{}); ok && tableble {
117+
rec = r
118+
} else {
119+
rec = map[string]interface{}{"value": val}
120+
tableble = false
121+
}
122+
if len(header) == 0 {
123+
header, err = makeHeader(rec)
124+
if err != nil {
125+
break
127126
}
128-
rows = append(rows, row)
129127
}
128+
var row []string
129+
for _, key := range header {
130+
cell := fmt.Sprintf("%v", rec[key])
131+
row = append(row, cell)
132+
}
133+
rows = append(rows, row)
130134
}
131135

132136
return
133137
}
134138

135-
func makeHeader(val interface{}) Header {
136-
var header Header
137-
r := reflect.ValueOf(val)
138-
for _, key := range r.MapKeys() {
139-
header = append(header, key.String())
139+
func makeHeader(m map[string]interface{}) (header Header, err error) {
140+
for key := range m {
141+
header = append(header, key)
140142
}
141143
sort.Strings(header)
142144
if len(*columns) > 0 {
@@ -149,5 +151,8 @@ func makeHeader(val interface{}) Header {
149151
}
150152
header = tmp
151153
}
152-
return header
154+
if len(header) == 0 {
155+
err = errors.New("Can't find specified column(s)")
156+
}
157+
return
153158
}

main_test.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,27 @@ var headertests = []headertestpair{
2020

2121
// TestMakeHeader to ensure we are getting sorted list of strings
2222
func TestMakeHeader(t *testing.T) {
23-
in := map[string]int{"b": 1, "z": 2, "a": 3, "r": 4, "o": 5}
23+
in := map[string]interface{}{"b": 1, "z": 2, "a": 3, "r": 4, "o": 5}
2424
for _, pair := range headertests {
2525
columns = pair.columns
26-
out := makeHeader(in)
26+
out, err := makeHeader(in)
27+
if err != nil {
28+
t.Fatal(err)
29+
}
2730
if !reflect.DeepEqual(pair.expect, out) {
2831
t.Errorf("Expecting %#v, got %#v", pair.expect, out)
2932
}
3033
}
34+
// return error
35+
columns = &ColumnsValue{"none"}
36+
out, err := makeHeader(in)
37+
if err == nil {
38+
t.Error("Expecting error, got nil")
39+
}
40+
var expect Header
41+
if !reflect.DeepEqual(expect, out) {
42+
t.Errorf("Expecting %#v, got %#v", expect, out)
43+
}
3144
}
3245

3346
// TestParseJSONObject to ensure we can parse JSON object
@@ -75,3 +88,32 @@ func TestParseJSONArray(t *testing.T) {
7588
t.Errorf("Expecting %#v, got %#v", expectRows, rows)
7689
}
7790
}
91+
92+
// TestParseMiscJSONArray to ensure we can parse arbitrary JSON array
93+
func TestParseMiscJSONArray(t *testing.T) {
94+
columns = &ColumnsValue{}
95+
r, err := os.Open("testdata/misc-array.json")
96+
if err != nil {
97+
t.Fatal(err)
98+
}
99+
header, rows, err := parseJSON(r)
100+
if err != nil {
101+
t.Fatal(err)
102+
}
103+
expectHeader := Header{"value"}
104+
if !reflect.DeepEqual(expectHeader, header) {
105+
t.Errorf("Expecting %#v, got %#v", expectHeader, header)
106+
}
107+
expectRows := Rows{
108+
[]string{"309"},
109+
[]string{"true"},
110+
[]string{"zG8dnbd1iXDHAewJ"},
111+
[]string{"false"},
112+
[]string{"773"},
113+
[]string{"Og3TQltUz2eIW6ZF"},
114+
[]string{"map[note:c#]"},
115+
}
116+
if !reflect.DeepEqual(expectRows, rows) {
117+
t.Errorf("Expecting %#v, got %#v", expectRows, rows)
118+
}
119+
}

testdata/misc-array.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[309,true,"zG8dnbd1iXDHAewJ",false,773,"Og3TQltUz2eIW6ZF",{"note":"c#"}]

0 commit comments

Comments
 (0)