Skip to content

Use encoding.TextUnmarshaler when MessagePack format is a str #370

@WGH-

Description

@WGH-

Expected Behavior

msgpack successfully unmarshals a type implementing both encoding.TextUnmarshaler and encoding.BinaryUnmashaler using the former interface when the data is of a str format, and is stored in text representation.

Current Behavior

msgpack fails to unmarshal the data in aforementioned conditions, because it's using the latter interface which does not expect text data.

This is because the library prefers BinaryUnmarshaler unconditionally:

msgpack/decode_value.go

Lines 73 to 78 in 19c91df

if typ.Implements(binaryUnmarshalerType) {
return nilAwareDecoder(typ, unmarshalBinaryValue)
}
if typ.Implements(textUnmarshalerType) {
return nilAwareDecoder(typ, unmarshalTextValue)
}

Possible Solution

Choose the preferred unmarshalling interface based on MessagePack format (MessagePack has distinct str and bin formats), preferring TextUnmarshaler when it's an str.

Steps to Reproduce

This example might look arbitrary out of context, but this situation easily arises when round-tripping the data through JSON and/or other libraries (especially in dynamically typed programming languages).

https://play.golang.com/p/3WFWbPVKDkp

package main

import (
	"log"

	"github.com/gofrs/uuid/v5"
	"github.com/vmihailenco/msgpack/v5"
)

type T struct {
	ID uuid.UUID
}

func main() {
	obj := map[string]any{
		"ID": "29247b08-ead7-46b3-b263-6944c2096673",
	}
	b, err := msgpack.Marshal(obj)
	if err != nil {
		panic(err)
	}

	var t T

	err = msgpack.Unmarshal(b, &t)
	if err != nil {
		panic(err)
	}

	log.Printf("%#v", t)
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions