award: json unmarshal

This commit is contained in:
Neale Pickett 2020-08-21 16:56:52 -06:00
parent f49d1c3801
commit b1b7fec6d1
2 changed files with 93 additions and 1 deletions

View File

@ -2,8 +2,11 @@
package award package award
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect"
"strconv"
"strings" "strings"
) )
@ -69,6 +72,80 @@ func (a T) MarshalJSON() ([]byte, error) {
return json.Marshal(ao) return json.Marshal(ao)
} }
// UnmarshalJSON decodes the JSON string b.
func (a T) UnmarshalJSON(b []byte) error {
r := bytes.NewReader(b)
dec := json.NewDecoder(r)
dec.UseNumber() // Don't use floats
// All this to make sure we get `[`
if t, err := dec.Token(); err != nil {
return err
} else {
switch token := t.(type) {
case json.Delim:
if token.String() != "[" {
return &json.UnmarshalTypeError{
Value: token.String(),
Type: reflect.TypeOf(a),
Offset: 0,
}
}
default:
return &json.UnmarshalTypeError{
Value: fmt.Sprintf("%v", t),
Type: reflect.TypeOf(a),
Offset: 0,
}
}
}
var num json.Number
var err error
if err := dec.Decode(&num); err != nil {
return err
}
if a.When, err = strconv.ParseInt(string(num), 10, 64); err != nil {
return err
}
if err := dec.Decode(&a.Category); err != nil {
return err
}
if err := dec.Decode(&a.TeamID); err != nil {
return err
}
if err := dec.Decode(&num); err != nil {
return err
}
if a.Points, err = strconv.Atoi(string(num)); err != nil {
return err
}
// All this to make sure we get `]`
if t, err := dec.Token(); err != nil {
return err
} else {
switch token := t.(type) {
case json.Delim:
if token.String() != "]" {
return &json.UnmarshalTypeError{
Value: token.String(),
Type: reflect.TypeOf(a),
Offset: 0,
}
}
default:
return &json.UnmarshalTypeError{
Value: fmt.Sprintf("%v", t),
Type: reflect.TypeOf(a),
Offset: 0,
}
}
}
return nil
}
// Equal returns true if two award events represent the same award. // Equal returns true if two award events represent the same award.
// Timestamps are ignored in this comparison! // Timestamps are ignored in this comparison!
func (a T) Equal(o T) bool { func (a T) Equal(o T) bool {

View File

@ -42,7 +42,8 @@ func TestAward(t *testing.T) {
t.Error("Different pount values compare equal") t.Error("Different pount values compare equal")
} }
if ja, err := a.MarshalJSON(); err != nil { ja, err := a.MarshalJSON()
if err != nil {
t.Error(err) t.Error(err)
} else if string(ja) != `[1536958399,"1a2b3c4d","counting",10]` { } else if string(ja) != `[1536958399,"1a2b3c4d","counting",10]` {
t.Error("JSON wrong") t.Error("JSON wrong")
@ -54,6 +55,20 @@ func TestAward(t *testing.T) {
if _, err := Parse("1 bad bad bad"); err == nil { if _, err := Parse("1 bad bad bad"); err == nil {
t.Error("Not throwing error on bad points") t.Error("Not throwing error on bad points")
} }
if err := b.UnmarshalJSON(ja); err != nil {
t.Error(err)
} else if !b.Equal(a) {
t.Error("UnmarshalJSON didn't work")
}
for _, s := range []string{`12`, `"moo"`, `{"a":1}`, `[1 2 3 4]`, `[]`, `[1,"a"]`, `[1,"a","b",4, 5]`} {
buf := []byte(s)
if err := a.UnmarshalJSON(buf); err == nil {
t.Error("Bad unmarshal didn't return error:", s)
}
}
} }
func TestAwardList(t *testing.T) { func TestAwardList(t *testing.T) {