diff --git a/decode.go b/decode.go index 5df40e5..d087275 100644 --- a/decode.go +++ b/decode.go @@ -16,6 +16,7 @@ import ( const ( looseInterfaceDecodingFlag uint32 = 1 << iota disallowUnknownFieldsFlag + ignoreMismatchedArrayFieldsFlag ) const ( @@ -135,6 +136,16 @@ func (d *Decoder) UseLooseInterfaceDecoding(on bool) { } } +// IgnoreMismatchedArrayFields causes the Decoder to ignore mismatch fields number in the +// array and struct. +func (d *Decoder) IgnoreMismatchedArrayFields(on bool) { + if on { + d.flags |= ignoreMismatchedArrayFieldsFlag + } else { + d.flags &= ^ignoreMismatchedArrayFieldsFlag + } +} + // SetCustomStructTag causes the decoder to use the supplied tag as a fallback option // if there is no msgpack tag. func (d *Decoder) SetCustomStructTag(tag string) { diff --git a/decode_map.go b/decode_map.go index 52e0526..da6414f 100644 --- a/decode_map.go +++ b/decode_map.go @@ -292,10 +292,14 @@ func decodeStructValue(d *Decoder, v reflect.Value) error { v.Set(reflect.Zero(v.Type())) return nil } - fields := structs.Fields(v.Type(), d.structTag) if n != len(fields.List) { - return errArrayStruct + if d.flags&ignoreMismatchedArrayFieldsFlag == 0 { + return errArrayStruct + } + if n < len(fields.List) { + fields.List = fields.List[:n] + } } for _, f := range fields.List { diff --git a/example_test.go b/example_test.go index 1408a59..15ae5ba 100644 --- a/example_test.go +++ b/example_test.go @@ -141,6 +141,70 @@ func ExampleEncoder_UseArrayEncodedStructs() { // Output: [foo bar] } +func ExampleDecoder_IgnoreMismatchedArrayFields() { + type Item struct { + Foo string + Bar string + } + type ItemLong struct { + Foo string + Bar string + Baz string + } + + var buf bytes.Buffer + + enc := msgpack.NewEncoder(&buf) + enc.UseArrayEncodedStructs(true) + + err := enc.Encode(&Item{Foo: "foo", Bar: "bar"}) + if err != nil { + panic(err) + } + + dec := msgpack.NewDecoder(&buf) + dec.IgnoreMismatchedArrayFields(true) + var itemLong ItemLong + err = dec.Decode(&itemLong) + if err != nil { + panic(err) + } + fmt.Println(itemLong) + // Output: {foo bar } +} + +func ExampleDecoder_IgnoreMismatchedArrayFields2() { + type Item struct { + Foo string + Bar string + } + type ItemLong struct { + Foo string + Bar string + Baz string + } + + var buf bytes.Buffer + + enc := msgpack.NewEncoder(&buf) + enc.UseArrayEncodedStructs(true) + + err := enc.Encode(&ItemLong{Foo: "foo", Bar: "bar", Baz: "baz"}) + if err != nil { + panic(err) + } + + dec := msgpack.NewDecoder(&buf) + dec.IgnoreMismatchedArrayFields(true) + var item Item + err = dec.Decode(&item) + if err != nil { + panic(err) + } + fmt.Println(item) + // Output: {foo bar} +} + func ExampleMarshal_asArray() { type Item struct { _msgpack struct{} `msgpack:",as_array"`