Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3698,6 +3698,73 @@ func TestDecodeContextOption(t *testing.T) {
})
}

type onlyContextUnmarshaler struct {
called bool
data string
}

func (u *onlyContextUnmarshaler) UnmarshalJSON(_ context.Context, b []byte) error {
u.called = true
u.data = string(b)
return nil
}

type onlyStdUnmarshaler struct {
called bool
data string
}

func (u *onlyStdUnmarshaler) UnmarshalJSON(b []byte) error {
u.called = true
u.data = string(b)
return nil
}

func TestUnmarshalerContextDispatch(t *testing.T) {
data := []byte(`{"name":"John"}`)

t.Run("context unmarshaler via Unmarshal", func(t *testing.T) {
var v onlyContextUnmarshaler
if err := json.Unmarshal(data, &v); err != nil {
t.Fatal(err)
}
if !v.called {
t.Fatal("UnmarshalJSON(context.Context, []byte) was not called")
}
})
t.Run("context unmarshaler via UnmarshalContext", func(t *testing.T) {
var v onlyContextUnmarshaler
if err := json.UnmarshalContext(context.Background(), data, &v); err != nil {
t.Fatal(err)
}
if !v.called {
t.Fatal("UnmarshalJSON(context.Context, []byte) was not called")
}
})
t.Run("std unmarshaler via UnmarshalContext", func(t *testing.T) {
var v onlyStdUnmarshaler
if err := json.UnmarshalContext(context.Background(), data, &v); err != nil {
t.Fatal(err)
}
if !v.called {
t.Fatal("UnmarshalJSON([]byte) was not called")
}
})
t.Run("std unmarshaler via Unmarshal matches encoding/json", func(t *testing.T) {
var v onlyStdUnmarshaler
if err := json.Unmarshal(data, &v); err != nil {
t.Fatal(err)
}
var std onlyStdUnmarshaler
if err := stdjson.Unmarshal(data, &std); err != nil {
t.Fatal(err)
}
if v.data != std.data {
t.Fatalf("go-json passed %q to UnmarshalJSON, encoding/json passed %q", v.data, std.data)
}
})
}

func TestIssue251(t *testing.T) {
array := [3]int{1, 2, 3}
err := stdjson.Unmarshal([]byte("[ ]"), &array)
Expand Down
15 changes: 11 additions & 4 deletions internal/decoder/unmarshal_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,20 @@ func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64,
typ: d.typ,
ptr: p,
}))
if (ctx.Option.Flags & ContextOption) != 0 {
if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
switch v := v.(type) {
case unmarshalerContext:
var c context.Context
if (ctx.Option.Flags & ContextOption) != 0 {
c = ctx.Option.Context
} else {
c = context.Background()
}
if err := v.UnmarshalJSON(c, dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
} else {
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
case json.Unmarshaler:
if err := v.UnmarshalJSON(dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
Expand Down