jsonint.Int is not longer an optional-type
parent
b499a1e144
commit
09e0626e3d
17
README.md
17
README.md
|
@ -9,3 +9,20 @@ This helps to work-around that numbers in JSON are effectively "broken".
|
||||||
Online documentation, which includes examples, can be found at: http://godoc.org/sourcecode.social/reiver/go-jsonint
|
Online documentation, which includes examples, can be found at: http://godoc.org/sourcecode.social/reiver/go-jsonint
|
||||||
|
|
||||||
[![GoDoc](https://godoc.org/sourcecode.social/reiver/go-jsonint?status.svg)](https://godoc.org/sourcecode.social/reiver/go-jsonint)
|
[![GoDoc](https://godoc.org/sourcecode.social/reiver/go-jsonint?status.svg)](https://godoc.org/sourcecode.social/reiver/go-jsonint)
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Here is an example:
|
||||||
|
```go
|
||||||
|
type Account struct {
|
||||||
|
FollowersCount jsonint.Int `json:"followers_count"`
|
||||||
|
FollowingCount jsonint.Int `json:"following_count"`
|
||||||
|
StatusexCount jsonint.Int `json:"statuses_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
var account Account
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &account)
|
||||||
|
```
|
||||||
|
|
|
@ -5,6 +5,5 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
errNilReceiver = erorr.Error("jsonint: nil receiver")
|
errNilReceiver = erorr.Error("jsonint: nil receiver")
|
||||||
errCannotMarshalNothingIntoJSON = erorr.Error("jsonint: cannot marshal jsonint.Nothing() into JSON")
|
|
||||||
)
|
)
|
||||||
|
|
43
int.go
43
int.go
|
@ -5,43 +5,45 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"sourcecode.social/reiver/go-erorr"
|
"sourcecode.social/reiver/go-erorr"
|
||||||
"sourcecode.social/reiver/go-opt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ json.Marshaler = Int{}
|
var _ json.Marshaler = Int{}
|
||||||
var _ json.Unmarshaler = new(Int)
|
var _ json.Unmarshaler = new(Int)
|
||||||
|
|
||||||
type Int struct {
|
type Int struct {
|
||||||
value opt.Optional[string]
|
value string
|
||||||
}
|
|
||||||
|
|
||||||
func Nothing() Int {
|
|
||||||
return Int{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Int64(value int64) Int {
|
func Int64(value int64) Int {
|
||||||
|
if 0 == value {
|
||||||
|
return Int{}
|
||||||
|
}
|
||||||
|
|
||||||
return Int{
|
return Int{
|
||||||
value: opt.Something(strconv.FormatInt(value, 10)),
|
value: strconv.FormatInt(value, 10),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uint64(value uint64) Int {
|
func Uint64(value uint64) Int {
|
||||||
return Int{
|
if 0 == value {
|
||||||
value: opt.Something(strconv.FormatUint(value, 10)),
|
return Int{}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (receiver Int) Get() (string, bool) {
|
return Int{
|
||||||
return receiver.value.Get()
|
value: strconv.FormatUint(value, 10),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver Int) MarshalJSON() ([]byte, error) {
|
func (receiver Int) MarshalJSON() ([]byte, error) {
|
||||||
value, found := receiver.value.Get()
|
return []byte(receiver.String()), nil
|
||||||
if !found {
|
}
|
||||||
return nil, errCannotMarshalNothingIntoJSON
|
|
||||||
|
func (receiver Int) String() string {
|
||||||
|
if "" == receiver.value {
|
||||||
|
return "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(value), nil
|
return receiver.value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (receiver *Int) UnmarshalJSON(data []byte) error {
|
func (receiver *Int) UnmarshalJSON(data []byte) error {
|
||||||
|
@ -53,7 +55,14 @@ func (receiver *Int) UnmarshalJSON(data []byte) error {
|
||||||
return erorr.Errorf("jsonint: cannot unmarshal %q into value of type %T", data, Int{})
|
return erorr.Errorf("jsonint: cannot unmarshal %q into value of type %T", data, Int{})
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.value = opt.Something(string(data))
|
s := string(data)
|
||||||
|
|
||||||
|
switch s {
|
||||||
|
case "0","-0","+0":
|
||||||
|
receiver.value = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver.value = string(data)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,13 @@ func TestInt_MarshalJSON(t *testing.T) {
|
||||||
Int jsonint.Int
|
Int jsonint.Int
|
||||||
Expected string
|
Expected string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
Int: jsonint.Int{},
|
||||||
|
Expected: "0",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Int: jsonint.Int64(-65537),
|
Int: jsonint.Int64(-65537),
|
||||||
Expected: "-65537",
|
Expected: "-65537",
|
||||||
|
@ -191,20 +198,3 @@ func TestInt_MarshalJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInt_MarshalJSON_fail(t *testing.T) {
|
|
||||||
|
|
||||||
var datum jsonint.Int
|
|
||||||
|
|
||||||
actualBytes, err := datum.MarshalJSON()
|
|
||||||
if nil == err {
|
|
||||||
t.Error("Expected an error but did not actually get one.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if nil != actualBytes {
|
|
||||||
t.Error("Expected return bytes to be nil but actually wasn't.")
|
|
||||||
t.Logf("ACTUAL BYTES: %#v", actualBytes)
|
|
||||||
t.Logf("ACTUAL BYTES: %q", actualBytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ package jsonint_test
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"sourcecode.social/reiver/go-jsonint"
|
"sourcecode.social/reiver/go-jsonint"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -251,3 +253,79 @@ func TestInt_UnmarshalJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInt_UnmarshalJSON_fail(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
JSON []byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
JSON: nil,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
JSON: []byte{},
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
JSON: []byte(""),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
JSON: []byte(" "),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte(" "),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte(" "),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
JSON: []byte("apple"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("banana"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("cherry"),
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
JSON: []byte("ONE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("TWO"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("THREE"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("FOUR"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
JSON: []byte("FIVE"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var actual jsonint.Int
|
||||||
|
|
||||||
|
err := json.Unmarshal(test.JSON, &actual)
|
||||||
|
if nil == err {
|
||||||
|
t.Errorf("For test #%d, expected an error but did not actually get one.", testNumber)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package jsonint_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"sourcecode.social/reiver/go-jsonint"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestZero(t *testing.T) {
|
||||||
|
|
||||||
|
var nothing jsonint.Int
|
||||||
|
|
||||||
|
var int64zero jsonint.Int = jsonint.Int64(0)
|
||||||
|
var uint64zero jsonint.Int = jsonint.Uint64(0)
|
||||||
|
|
||||||
|
var jsonzero jsonint.Int
|
||||||
|
{
|
||||||
|
var data []byte = []byte("0")
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, &jsonzero)
|
||||||
|
if nil != err {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nothing != int64zero {
|
||||||
|
t.Error("nothing ≠ int64zero")
|
||||||
|
}
|
||||||
|
if nothing != uint64zero {
|
||||||
|
t.Error("nothing ≠ uint64zero")
|
||||||
|
}
|
||||||
|
if nothing != jsonzero {
|
||||||
|
t.Error("nothing ≠ json64zero")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue