Skip to content

Commit ac139e1

Browse files
committed
JSON unmarshaler returns UnknownFieldError error struct for unknown fields.
1 parent 4bd1920 commit ac139e1

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

jsonpb/jsonpb.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,20 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
510510
return out.err
511511
}
512512

513+
// UnknownFieldError is an error if an unknown field was encountered
514+
// during unmarshaling.
515+
type UnknownFieldError struct {
516+
// Field is the name of the JSON field.
517+
Field string
518+
519+
// TargetType is the type attempted unmarshaled.
520+
TargetType reflect.Type
521+
}
522+
523+
func (u UnknownFieldError) Error() string {
524+
return fmt.Sprintf("unknown field %q in %v", u.Field, u.TargetType)
525+
}
526+
513527
// Unmarshaler is a configurable object for converting from a JSON
514528
// representation to a protocol buffer object.
515529
type Unmarshaler struct {
@@ -701,7 +715,10 @@ func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMe
701715
f = fname
702716
break
703717
}
704-
return fmt.Errorf("unknown field %q in %v", f, targetType)
718+
return UnknownFieldError{
719+
Field: f,
720+
TargetType: targetType,
721+
}
705722
}
706723
return nil
707724
}

jsonpb/jsonpb_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,29 @@ func TestUnmarshaling(t *testing.T) {
504504
}
505505
}
506506

507+
func TestUnmarshalDisallowingUnknownField(t *testing.T) {
508+
u := Unmarshaler{AllowUnknownFields: false}
509+
err := u.Unmarshal(strings.NewReader(`{"unknown": "foo"}`), simpleObject)
510+
if err == nil {
511+
t.Errorf("expected error, got nil")
512+
return
513+
}
514+
fieldErr, ok := err.(UnknownFieldError)
515+
if !ok {
516+
t.Errorf("expected error to be UnknownFieldError, got %T", fieldErr)
517+
return
518+
}
519+
if fieldErr.Field != "unknown" {
520+
t.Errorf("expected field to be %q, got %q", "unknown", fieldErr.Field)
521+
return
522+
}
523+
if fieldErr.TargetType.Name() != reflect.TypeOf(*simpleObject).Name() {
524+
t.Errorf("expected target type to be %T, got %T",
525+
reflect.TypeOf(*simpleObject), fieldErr.TargetType)
526+
return
527+
}
528+
}
529+
507530
func TestUnmarshalNext(t *testing.T) {
508531
// We only need to check against a few, not all of them.
509532
tests := unmarshalingTests[:5]

0 commit comments

Comments
 (0)