polenter / SharpSerializer

SharpSerializer can serialize types like: multidimensional array, nested array, array-of-arrays, polymorphic object (where value is inherited from the property type), generic type, generic listing (i.e. dictionary, collection) and many more, with a single line of code
https://www.sharpserializer.net
Other
114 stars 28 forks source link

DeserializingException, An item with the same key has already been added. Second time deserialization #15

Closed Kluez closed 3 years ago

Kluez commented 3 years ago

Hi,

we had a strange issue in our tests when we added SharpSerializer serialization/deserialization (v 3.0.1) to our caching. The second time we deserialize a list, which contains the same element several times we get the exceptions.

    class Foo
    {
        public string ID { get; set; } = Guid.NewGuid().ToString();
    }

    [Fact]
    public async Task Serialization_DeSerializationFails__IfTheObjectsAreTheSame()
    {
        var data = Enumerable.Repeat(new Foo(), 2).ToList(); //same object, same reference
        var deSerializedOk = data.ToByteArray().FromByteArray<List<Foo>>();
        var deSerializedFails = data.ToByteArray().FromByteArray<List<Foo>>();
    }

The extension methods are like:

    private static readonly SharpSerializer Serializer = new SharpSerializer(new SharpSerializerBinarySettings()
    {
        Encoding = Encoding.Unicode
    });

    public static byte[] ToByteArray<tt>(this tt obj)
    {
        if (obj == null)
            return null;

        using (var ms = new MemoryStream())
        {
            Serializer.Serialize(obj, ms);
            return ms.ToArray();
        }
    }

    public static tt FromByteArray<tt>(this byte[] data)
    {
        if (data == null)
            return default(tt);

        using (MemoryStream ms = new MemoryStream(data,false))
        {
            var obj = Serializer.Deserialize(ms);
            if (obj is tt deserialized)
                return deserialized;
            return default(tt);
        }
    }

Exceptions stacktrace:

System.ArgumentException An item with the same key has already been added. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add) at Polenter.Serialization.Advanced.BinaryPropertyDeserializer.deserialize(Byte elementId, String propertyName, Type expectedType) at Polenter.Serialization.Advanced.BinaryPropertyDeserializer.readItems(ICollection1 items, Type expectedElementType) at Polenter.Serialization.Advanced.BinaryPropertyDeserializer.deserialize(Byte elementId, String propertyName, Type expectedType) at Polenter.Serialization.Advanced.BinaryPropertyDeserializer.Deserialize() at Polenter.Serialization.SharpSerializer.Deserialize(Stream stream)

Any help would really be appreciated!

Kluez commented 3 years ago

Using new SharpSerializer() instead of static solves the issue.