Skip to content

Commit

Permalink
Merge branch 'fix-number-float'
Browse files Browse the repository at this point in the history
  • Loading branch information
yukithm committed Apr 27, 2016
2 parents c8c64e3 + bce90ab commit b3db7b4
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 20 deletions.
11 changes: 4 additions & 7 deletions cmd/json2csv/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"

Expand All @@ -19,7 +18,7 @@ const (
ApplicationName = "json2csv"

// Version is the version number of this application.
Version = "0.1.0"
Version = "0.1.1"
)

var headerStyleTable = map[string]json2csv.KeyStyle{
Expand Down Expand Up @@ -145,13 +144,11 @@ func readJSONFile(filename string) (interface{}, error) {
}

func readJSON(r io.Reader) (interface{}, error) {
buf, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
decoder := json.NewDecoder(r)
decoder.UseNumber()

var data interface{}
if err := json.Unmarshal(buf, &data); err != nil {
if err := decoder.Decode(&data); err != nil {
return nil, err
}

Expand Down
11 changes: 11 additions & 0 deletions flatten.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package json2csv

import (
"encoding/json"
"fmt"
"reflect"
"sort"
Expand All @@ -9,6 +10,8 @@ import (
"github.com/yukithm/json2csv/jsonpointer"
)

var jsonNumberType = reflect.TypeOf(json.Number(""))

type mapKeys []reflect.Value

func (k mapKeys) Len() int { return len(k) }
Expand Down Expand Up @@ -51,6 +54,14 @@ func _flatten(out KeyValue, obj interface{}, key jsonpointer.JSONPointer) error
value = value.Elem()
}

if value.IsValid() {
vt := value.Type()
if vt.AssignableTo(jsonNumberType) {
out[key.String()] = value.Interface().(json.Number)
return nil
}
}

switch value.Kind() {
case reflect.Map:
_flattenMap(out, value, key)
Expand Down
48 changes: 35 additions & 13 deletions json2csv_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
package json2csv

import (
"bytes"
"encoding/json"
"reflect"
"testing"
)

// Decode JSON with UseNumber option.
func json2obj(jsonstr string) (interface{}, error) {
r := bytes.NewReader([]byte(jsonstr))
d := json.NewDecoder(r)
d.UseNumber()
var obj interface{}
if err := d.Decode(&obj); err != nil {
return nil, err
}
return obj, nil
}

var testJSON2CSVCases = []struct {
json string
expected []KeyValue
Expand All @@ -17,8 +30,8 @@ var testJSON2CSVCases = []struct {
{"id": 2, "name": "bar"}
]`,
[]KeyValue{
{"/id": 1.0, "/name": "foo"},
{"/id": 2.0, "/name": "bar"},
{"/id": json.Number("1"), "/name": "foo"},
{"/id": json.Number("2"), "/name": "bar"},
},
``,
},
Expand All @@ -28,8 +41,8 @@ var testJSON2CSVCases = []struct {
{"id": 2, "name~b": "bar"}
]`,
[]KeyValue{
{"/id": 1.0, "/name~1a": "foo"},
{"/id": 2.0, "/name~0b": "bar"},
{"/id": json.Number("1"), "/name~1a": "foo"},
{"/id": json.Number("2"), "/name~0b": "bar"},
},
``,
},
Expand All @@ -39,8 +52,8 @@ var testJSON2CSVCases = []struct {
{"id":2, "values":["x"]}
]`,
[]KeyValue{
{"/id": 1.0, "/values/0": "a", "/values/1": "b"},
{"/id": 2.0, "/values/0": "x"},
{"/id": json.Number("1"), "/values/0": "a", "/values/1": "b"},
{"/id": json.Number("2"), "/values/0": "x"},
},
``,
},
Expand All @@ -50,8 +63,8 @@ var testJSON2CSVCases = []struct {
{"id":2, "values":["x"]}
]`,
[]KeyValue{
{"/id": 1.0},
{"/id": 2.0, "/values/0": "x"},
{"/id": json.Number("1")},
{"/id": json.Number("2"), "/values/0": "x"},
},
``,
},
Expand All @@ -61,8 +74,8 @@ var testJSON2CSVCases = []struct {
{"id":2, "values":["x"]}
]`,
[]KeyValue{
{"/id": 1.0},
{"/id": 2.0, "/values/0": "x"},
{"/id": json.Number("1")},
{"/id": json.Number("2"), "/values/0": "x"},
},
``,
},
Expand All @@ -75,7 +88,7 @@ var testJSON2CSVCases = []struct {
]
}`,
[]KeyValue{
{"/id": 123.0, "/values/0/foo": "FOO", "/values/1/bar": "BAR"},
{"/id": json.Number("123"), "/values/0/foo": "FOO", "/values/1/bar": "BAR"},
},
``,
},
Expand All @@ -89,15 +102,24 @@ var testJSON2CSVCases = []struct {
[]KeyValue{},
``,
},
{
`{"large_int_value": 146163870300}`,
[]KeyValue{{"/large_int_value": json.Number("146163870300")}},
``,
},
{
`{"float_value": 146163870.300}`,
[]KeyValue{{"/float_value": json.Number("146163870.300")}},
``,
},
{`"foo"`, nil, `Unsupported JSON structure.`},
{`123`, nil, `Unsupported JSON structure.`},
{`true`, nil, `Unsupported JSON structure.`},
}

func TestJSON2CSV(t *testing.T) {
for caseIndex, testCase := range testJSON2CSVCases {
var obj interface{}
err := json.Unmarshal([]byte(testCase.json), &obj)
obj, err := json2obj(testCase.json)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit b3db7b4

Please sign in to comment.