msgpack / msgpack-cli

MessagePack implementation for Common Language Infrastructure / msgpack.org[C#]
http://msgpack.org
Apache License 2.0
835 stars 175 forks source link

MsgPack 1.0.0 throws ExtendedTypeObject is prohibited in this packer. #300

Open odyth opened 6 years ago

odyth commented 6 years ago

I have an object that doesn't extend from anything yet when I updated from 0.9.2 to 1.0.0 I get "ExtendedTypeObject is prohibited in this packer." when trying to pack an object. My object isn't anything fancy just strings, ints, and datetimes.

I am using .net 4.7.2 and below is how I am trying to pack an object.

var type = value.GetType();
var typeName = WriteCache.GetOrAdd(type, SubtractFullNameRegex.Replace(type.AssemblyQualifiedName, string.Empty)); // Get type or Register type
using (MemoryStream memoryStream = new MemoryStream())
{
    Packer packer = Packer.Create(memoryStream);
    packer.PackArrayHeader(2);
    packer.PackString(typeName);
    try
    {
        MessagePackSerializer.Get(type, DefaultContext).PackTo(packer, value);
        return new ArraySegment<byte>(memoryStream.ToArray(), 0, (int)memoryStream.Length);
    }
    catch (Exception ex)
    {
        Logger.LogError("MessagePackMapTranscoder", ex, new Dictionary<string, object>
        {
            ["TypeName"] = typeName
        });
        throw;
    }
}

Here is the object I am trying to pack.

[Table]
public class Company
{
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int Id { get; set; }

    [Column]
    public string Name { get; set; }

    [Column]
    public string Address { get; set; }

    [Column]
    public string City { get; set; }

    [Column]
    public string State { get; set; }

    [Column]
    public string Zip { get; set; }

    [Column]
    public string PhoneNumber { get; set; }

    [Column]
    public DateTime Created { get; set; }

    [Column(IsVersion = true)]
    public DateTime Updated { get; set; }

    [Column(IsVersion = true)]
    public int TimeStamp { get; set; }

    [Column]
    public string TemplatedLogoUrl { get; set; }

    [Column]
    public string UrlName { get; set; }
}

Stacktrace of exception

   at MsgPack.Packer.ThrowExtTypeIsProhibitedException()
   at MsgPack.Packer.PackExtendedTypeValue(MessagePackExtendedTypeObject mpeto)
   at MsgPack.Serialization.DefaultSerializers.MsgPack_MessagePackExtendedTypeObjectMessagePackSerializer.PackToCore(Packer packer, MessagePackExtendedTypeObject value)
   at MsgPack.Serialization.MessagePackSerializer`1.PackTo(Packer packer, T objectTree)
   at MsgPack.PackerUnpackerExtensions.PackCore[T](Packer source, T value, SerializationContext context)
   at MsgPack.PackerUnpackerExtensions.Pack[T](Packer source, T value)
   at MsgPack.Serialization.DefaultSerializers.TimestampDateTimeMessagePackSerializer.PackToCore(Packer packer, DateTime objectTree)
   at MsgPack.Serialization.MessagePackSerializer`1.PackTo(Packer packer, T objectTree)
   at MsgPack.Serialization.PackHelpers.PackToMap[TObject](PackToMapParameters`1& parameter)
   at MsgPack.Serialization.EmittingSerializers.Generated.MyNameSpace_CompanySerializer1.PackToCore(Packer , Company )
   at MsgPack.Serialization.MessagePackSerializer`1.InternalPackTo(Packer packer, Object objectTree)
   at MyNameSpace.MessagePackMapTranscoder.SerializeObject(Object value) in MessagePackMapTranscoder.cs:line 191 (THIS IS MY CODE)
   at MyNameSpace.MessagePackMapTranscoder.Serialize(Object value) in MessagePackMapTranscoder.cs:line 63 (THIS IS MY CODE)
   at Enyim.Caching.MemcachedClient.PerformStore(StoreMode mode, String key, Object value, UInt32 expires, UInt64& cas, Int32& statusCode) (THIS IS MY CODE)
yfakariya commented 6 years ago

It looks caused by changing default date time serializer between 0.9 to 1.0. This change was intended to improve interoperability for other languages which uses ext-typed timestamp for datetime like values.

You can avoid this error by one of following:

  1. Allow ext type in the context. Namely, SerializationContext.Default.CompatibilityOptions.PackerCompatibilityOptions &= ~PackerCompatibilityOptions.ProhibitExtendedTypeObjects
  2. Change default timestamp serializer to previous one by SerializationContext.Default.DefaultDateTimeConversionMethod = DateTimeConversionMethod.Native

I will also add context options to change behavior to 0.9 for compatibility in 1.1.