microsoft-avro
microsoft-avro copied to clipboard
Broken Serialization/Deserialization of complicated object
Below is a reproduction of an issue where a List containing a List containing a Dictionary doesn't seem to serialize/deserialize properly. From what I can tell, the second Grandchildren.Enums gets serialized incorrectly, and the deserialization blows up when attempting to read it. My suspicion is that the EnumerableSerializer is causing the issue; however, I'm not sure how best to address it. The code below is the minimal reproduction that I was able to create for this issue.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using FluentAssertions;
using Microsoft.Hadoop.Avro;
using Xunit;
namespace Microsoft.Avro.Tests.MyTests
{
public class BrokenStuff
{
[Fact]
public void Repro()
{
var data = new Container
{
Children = new List<Child>
{
new Child()
{
Granchildren = new List<Grandchildren>
{
new Grandchildren { Enums = new Dictionary<TestEnum, string> {{ TestEnum.Val1, "testval1"}}},
new Grandchildren { Enums = new Dictionary<TestEnum, string> {{ TestEnum.Val2, "testval2"}}}
}
},
}
};
RoundTripSerializationWithCheck(data,
actual => actual.ShouldBeEquivalentTo(data),
new AvroSerializerSettings
{
Resolver = new AvroPublicMemberContractResolver(true),
});
}
private static TS RoundTripSerializationWithCheck<TS>(TS serialized, Action<TS> check, AvroSerializerSettings settings = null)
{
if (check == null)
{
throw new ArgumentNullException("check");
}
var serializer = settings == null
? AvroSerializer.Create<TS>(new AvroSerializerSettings { Resolver = new AvroDataContractResolver(true) })
: AvroSerializer.Create<TS>(settings);
using (var stream = new MemoryStream())
{
serializer.Serialize(stream, serialized);
stream.Seek(0, SeekOrigin.Begin);
var bytes = stream.ToArray();
var chars = bytes.Select(Convert.ToChar).ToArray();
Debugger.Break();
var deserialized = serializer.Deserialize(stream);
check(deserialized);
return deserialized;
}
}
public class Container
{
public List<Child> Children { get; set; }
}
public class Child
{
public List<Grandchildren> Granchildren { get; set; }
}
public class Grandchildren
{
public Dictionary<TestEnum, string> Enums { get; set; }
}
public enum TestEnum
{
Val1,
Val2
}
}
}