Skip to content

Commit d8927ad

Browse files
authored
Add unmarshal funcs (#8)
1 parent 1ef60ba commit d8927ad

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

jsn.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
package jsn
22

3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"io"
8+
)
9+
310
// A represents JSON array.
411
type A = []any
512

@@ -15,3 +22,26 @@ type N string
1522
func (n N) MarshalJSON() ([]byte, error) {
1623
return []byte(n), nil
1724
}
25+
26+
// Unmarshal only 1 JSON entity from the input.
27+
// Disallows unknown fields if the argument is a struct.
28+
func Unmarshal(b []byte, v any) error {
29+
return UnmarshalFrom(bytes.NewReader(b), v)
30+
}
31+
32+
// UnmarshalFrom only 1 JSON entity from the input.
33+
// Disallows unknown fields if the argument is a struct.
34+
func UnmarshalFrom(r io.Reader, v any) error {
35+
d := json.NewDecoder(r)
36+
d.DisallowUnknownFields()
37+
38+
if err := d.Decode(v); err != nil {
39+
return err
40+
}
41+
if d.More() {
42+
return errMore
43+
}
44+
return nil
45+
}
46+
47+
var errMore = errors.New("body must contain only one JSON entity")

jsn_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package jsn
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
)
7+
8+
func TestUnmarshal(t *testing.T) {
9+
testCases := []struct {
10+
input string
11+
want any
12+
errStr string
13+
}{
14+
{
15+
input: `"abc"`,
16+
want: "abc",
17+
},
18+
{
19+
input: `123`,
20+
want: float64(123),
21+
},
22+
{
23+
input: `{"abc": 123}`,
24+
want: map[string]any{"abc": float64(123)},
25+
},
26+
{
27+
input: `{"abc": 123} `,
28+
want: map[string]any{"abc": float64(123)},
29+
},
30+
{
31+
input: ` ["abc", 123] `,
32+
want: []any{"abc", float64(123)},
33+
},
34+
{
35+
input: `{"abc": 123}a`,
36+
errStr: "body must contain only one JSON entity",
37+
},
38+
{
39+
input: `[123]{"a":"b"}`,
40+
errStr: "body must contain only one JSON entity",
41+
},
42+
{
43+
input: `{"abc`,
44+
errStr: "unexpected EOF",
45+
},
46+
}
47+
48+
for _, tc := range testCases {
49+
var val any
50+
err := Unmarshal([]byte(tc.input), &val)
51+
if err != nil {
52+
if tc.errStr == "" {
53+
t.Fatal(err)
54+
}
55+
if have := err.Error(); have != tc.errStr {
56+
t.Fatalf("\nhave: %+v\nwant: %+v\n", have, tc.errStr)
57+
}
58+
continue
59+
}
60+
61+
if !reflect.DeepEqual(val, tc.want) {
62+
t.Fatalf("\nhave: %+v\nwant: %+v\n", val, tc.want)
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)