-
Notifications
You must be signed in to change notification settings - Fork 498
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use json.Number internally, to handle both int64 and float64
This defers the actual parsing of the text value to the numeric type until you dereference it using the Int(), Int64() or Float64() receiver methods. This has the benefit that large integers (>= 1e6) are not marshaled in floating point exponent notation, and that very large integers (>= 2^53) do not lose precision when marshaled because they were stored internally as float64s. This retains backward compatibility with Go 1.0.x because it doesn't have json.Number.
- Loading branch information
1 parent
9002e63
commit 7f4699f
Showing
6 changed files
with
175 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// +build !go1.1 | ||
|
||
package simplejson | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
) | ||
|
||
// Implements the json.Unmarshaler interface. | ||
func (j *Json) UnmarshalJSON(p []byte) error { | ||
return json.Unmarshal(p, &j.data) | ||
} | ||
|
||
// Float64 type asserts to `float64` | ||
func (j *Json) Float64() (float64, error) { | ||
if i, ok := (j.data).(float64); ok { | ||
return i, nil | ||
} | ||
return -1, errors.New("type assertion to float64 failed") | ||
} | ||
|
||
// Int type asserts to `float64` then converts to `int` | ||
func (j *Json) Int() (int, error) { | ||
if f, ok := (j.data).(float64); ok { | ||
return int(f), nil | ||
} | ||
|
||
return -1, errors.New("type assertion to float64 failed") | ||
} | ||
|
||
// Int type asserts to `float64` then converts to `int64` | ||
func (j *Json) Int64() (int64, error) { | ||
if f, ok := (j.data).(float64); ok { | ||
return int64(f), nil | ||
} | ||
|
||
return -1, errors.New("type assertion to float64 failed") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// +build !go1.1 | ||
|
||
package simplejson | ||
|
||
import ( | ||
"github.com/bmizerany/assert" | ||
"io/ioutil" | ||
"log" | ||
"strconv" | ||
"testing" | ||
) | ||
|
||
func TestSimplejsonGo10(t *testing.T) { | ||
log.SetOutput(ioutil.Discard) | ||
|
||
js, err := NewJson([]byte(`{ | ||
"test": { | ||
"array": [1, "2", 3], | ||
"arraywithsubs": [{"subkeyone": 1}, | ||
{"subkeytwo": 2, "subkeythree": 3}] | ||
} | ||
}`)) | ||
|
||
assert.NotEqual(t, nil, js) | ||
assert.Equal(t, nil, err) | ||
|
||
arr, _ := js.Get("test").Get("array").Array() | ||
assert.NotEqual(t, nil, arr) | ||
for i, v := range arr { | ||
var iv int | ||
switch v.(type) { | ||
case float64: | ||
iv = int(v.(float64)) | ||
case string: | ||
iv, _ = strconv.Atoi(v.(string)) | ||
} | ||
assert.Equal(t, i+1, iv) | ||
} | ||
|
||
ma := js.Get("test").Get("array").MustArray() | ||
assert.Equal(t, ma, []interface{}{float64(1), "2", float64(3)}) | ||
|
||
mm := js.Get("test").Get("arraywithsubs").GetIndex(0).MustMap() | ||
assert.Equal(t, mm, map[string]interface{}{"subkeyone": float64(1)}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// +build go1.1 | ||
|
||
package simplejson | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"errors" | ||
) | ||
|
||
// Implements the json.Unmarshaler interface. | ||
func (j *Json) UnmarshalJSON(p []byte) error { | ||
dec := json.NewDecoder(bytes.NewBuffer(p)) | ||
dec.UseNumber() | ||
return dec.Decode(&j.data) | ||
} | ||
|
||
// Float64 type asserts to `json.Number` then converts to `float64` | ||
func (j *Json) Float64() (float64, error) { | ||
if n, ok := (j.data).(json.Number); ok { | ||
return n.Float64() | ||
} | ||
return -1, errors.New("type assertion to float64 failed") | ||
} | ||
|
||
// Int type asserts to `json.Number` then converts to `int` | ||
func (j *Json) Int() (int, error) { | ||
if n, ok := (j.data).(json.Number); ok { | ||
i, ok := n.Int64() | ||
return int(i), ok | ||
} | ||
|
||
return -1, errors.New("type assertion to float64 failed") | ||
} | ||
|
||
// Int type asserts to `json.Number` then converts to `int64` | ||
func (j *Json) Int64() (int64, error) { | ||
if n, ok := (j.data).(json.Number); ok { | ||
return n.Int64() | ||
} | ||
|
||
return -1, errors.New("type assertion to float64 failed") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// +build go1.1 | ||
|
||
package simplejson | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/bmizerany/assert" | ||
"io/ioutil" | ||
"log" | ||
"strconv" | ||
"testing" | ||
) | ||
|
||
func TestSimplejsonGo11(t *testing.T) { | ||
log.SetOutput(ioutil.Discard) | ||
|
||
js, err := NewJson([]byte(`{ | ||
"test": { | ||
"array": [1, "2", 3], | ||
"arraywithsubs": [{"subkeyone": 1}, | ||
{"subkeytwo": 2, "subkeythree": 3}] | ||
} | ||
}`)) | ||
|
||
assert.NotEqual(t, nil, js) | ||
assert.Equal(t, nil, err) | ||
|
||
arr, _ := js.Get("test").Get("array").Array() | ||
assert.NotEqual(t, nil, arr) | ||
for i, v := range arr { | ||
var iv int | ||
switch v.(type) { | ||
case json.Number: | ||
i64, err := v.(json.Number).Int64() | ||
assert.Equal(t, nil, err) | ||
iv = int(i64) | ||
case string: | ||
iv, _ = strconv.Atoi(v.(string)) | ||
} | ||
assert.Equal(t, i+1, iv) | ||
} | ||
|
||
ma := js.Get("test").Get("array").MustArray() | ||
assert.Equal(t, ma, []interface{}{json.Number("1"), "2", json.Number("3")}) | ||
|
||
mm := js.Get("test").Get("arraywithsubs").GetIndex(0).MustMap() | ||
assert.Equal(t, mm, map[string]interface{}{"subkeyone": json.Number("1")}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters