jsonint.Int is not longer an optional-type

master
Charles Iliya Krempeaux 2023-09-25 06:29:05 +09:00
parent b499a1e144
commit 09e0626e3d
6 changed files with 166 additions and 36 deletions

View File

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

View File

@ -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
View File

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

View File

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

View File

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

37
zero_test.go 100644
View File

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