✨ Entry implements json.Unmarshaler
This commit is contained in:
parent
eff9a454f9
commit
0da5efcafe
2 changed files with 53 additions and 6 deletions
|
|
@ -179,6 +179,50 @@ func (e Entry) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(out)
|
return json.Marshal(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entry) UnmarshalJSON([]byte) error {
|
func (e *Entry) UnmarshalJSON(in []byte) error {
|
||||||
|
out := map[string]any{}
|
||||||
|
dec := json.NewDecoder(bytes.NewReader(in))
|
||||||
|
dec.UseNumber()
|
||||||
|
err := dec.Decode(&out)
|
||||||
|
if err != nil {
|
||||||
|
return newParsingError(err)
|
||||||
|
}
|
||||||
|
title, ok := out["title"].(string)
|
||||||
|
if !ok || title == "" {
|
||||||
|
return ErrorMissingTitle
|
||||||
|
}
|
||||||
|
e.Title = title
|
||||||
|
delete(out, "title")
|
||||||
|
dates, ok := out["date"].(string)
|
||||||
|
if !ok || dates == "" {
|
||||||
|
return ErrorMissingDate
|
||||||
|
}
|
||||||
|
date, err := time.Parse(time.RFC3339, dates)
|
||||||
|
if err != nil {
|
||||||
|
return newParsingError(err)
|
||||||
|
}
|
||||||
|
e.Date = date
|
||||||
|
delete(out, "date")
|
||||||
|
for k, v := range out {
|
||||||
|
m := Meta{Key: k}
|
||||||
|
if vs, ok := v.(string); ok {
|
||||||
|
if vd, err := time.Parse(time.RFC3339, vs); err == nil {
|
||||||
|
m.Value = vd
|
||||||
|
} else {
|
||||||
|
m.Value = vs
|
||||||
|
}
|
||||||
|
} else if n, ok := v.(json.Number); ok {
|
||||||
|
it, _ := n.Int64()
|
||||||
|
fl, _ := n.Float64()
|
||||||
|
if float64(it) == fl {
|
||||||
|
m.Value = it
|
||||||
|
} else {
|
||||||
|
m.Value = fl
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m.Value = v
|
||||||
|
}
|
||||||
|
e.Fields = append(e.Fields, m)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ func getEntryJsonMarshalTestRunner(title string, date time.Time, fields []Meta,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEntryJsonUnmarshal(t *testing.T) {
|
func TestEntryJsonUnmarshal(t *testing.T) {
|
||||||
when := time.Now()
|
when := time.Now().Truncate(time.Second)
|
||||||
whens := when.Format(time.RFC3339)
|
whens := when.Format(time.RFC3339)
|
||||||
simple := []Meta{}
|
simple := []Meta{}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
@ -250,6 +250,7 @@ func TestEntryJsonUnmarshal(t *testing.T) {
|
||||||
{"empty-title", `{"title":"","date":"` + whens + `"}`, "", when, simple, ErrorMissingTitle},
|
{"empty-title", `{"title":"","date":"` + whens + `"}`, "", when, simple, ErrorMissingTitle},
|
||||||
{"empty-date", `{"title":"A Title","date":""}`, "", when, simple, ErrorMissingDate},
|
{"empty-date", `{"title":"A Title","date":""}`, "", when, simple, ErrorMissingDate},
|
||||||
{"bad-date", `{"title":"A Title","date":"bad"}`, "", when, simple, ErrorParsing},
|
{"bad-date", `{"title":"A Title","date":"bad"}`, "", when, simple, ErrorParsing},
|
||||||
|
{"bad-json", `{"title":"A Title","date":"`, "", when, simple, ErrorParsing},
|
||||||
{
|
{
|
||||||
"single-field",
|
"single-field",
|
||||||
`{"title":"A Title","date":"` + whens + `","hello":"Hi"}`,
|
`{"title":"A Title","date":"` + whens + `","hello":"Hi"}`,
|
||||||
|
|
@ -260,10 +261,10 @@ func TestEntryJsonUnmarshal(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"many-fields",
|
"many-fields",
|
||||||
`{"title":"A Title","date":"` + whens + `","hello":"Hi","bye":42,"b":true}`,
|
`{"title":"A Title","date":"` + whens + `","hello":"Hi","bye":42,"b":true,"fl":42.13}`,
|
||||||
"A Title",
|
"A Title",
|
||||||
when,
|
when,
|
||||||
[]Meta{{"hello", "Hi"}, {"bye", 42}, {"b", true}},
|
[]Meta{{"hello", "Hi"}, {"bye", int64(42)}, {"b", true}, {"fl", float64(42.13)}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -284,14 +285,16 @@ func TestEntryJsonUnmarshal(t *testing.T) {
|
||||||
func getEntryJsonUnmarshalTestRunner(in, title string, date time.Time, fields []Meta, err error) func(t *testing.T) {
|
func getEntryJsonUnmarshalTestRunner(in, title string, date time.Time, fields []Meta, err error) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
e := new(Entry)
|
e := new(Entry)
|
||||||
er := json.Unmarshal([]byte(in), e)
|
er := e.UnmarshalJSON([]byte(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
assert.ErrorIs(t, er, err)
|
assert.ErrorIs(t, er, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert.Nil(t, er)
|
||||||
assert.Equal(t, title, e.Title)
|
assert.Equal(t, title, e.Title)
|
||||||
assert.WithinRange(t, e.Date, date.Add(-time.Second), date.Add(time.Second))
|
assert.WithinRange(t, e.Date, date.Add(-time.Second), date.Add(time.Second))
|
||||||
|
assert.Len(t, e.Fields, len(fields))
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
got := false
|
got := false
|
||||||
for _, m := range e.Fields {
|
for _, m := range e.Fields {
|
||||||
|
|
@ -308,7 +311,7 @@ func getEntryJsonUnmarshalTestRunner(in, title string, date time.Time, fields []
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Truef(t, got, "Couldn't find field %+v", f)
|
assert.Truef(t, got, "Couldn't find field %+v. We have %+v", f, e.Fields)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue