ExtendedXmlSerializer/home

Serializing empty lists

Closed this issue ยท 12 comments

Thanks again for this great tool!

I noticed that the serializer treats empty lists the same as unassigned ones (containing null). In both cases, null is written to the property at desirialization.
Is this an intended behavior?
Is it possible to change this behavior by adjusting the configuration?

Hey @imperiobadgo thank you for the kind words and for writing in with the question. It turns out that this is indeed configurable via the Emit configuration as shown here:

[Fact]
public void Verify()
{
var instance = new Subject{ List = new List<string>() };
var container = new ConfigurationContainer().Emit(EmitBehaviors.Classic).Create().ForTesting();
container.Cycle(instance).Should().BeEquivalentTo(instance);
}

There are a few others but EmitBehaviors.Classic emits empty lists and Enum values.

Let me know if that situates you in the right direction and/or if you have any further questions I will see if I can assist. ๐Ÿ‘

Thank you very much for your quick reply!!! Is it also possible to define the emit behavior only for certain types?

You sure can, @imperiobadgo. Here's another test demonstrating the EmitWhen for both type and members for your review:

[Fact]
public void VerifyNotEmit()
{
var instance = new EmitMe()
{
Message = "This is emitted",
NotEmitted = new DoNotEmitMe { Message = "But I want to be emitted... :( :( :(" }
};
var container = new ConfigurationContainer().Type<DoNotEmitMe>()
.EmitWhen(_ => false)
.Member(x => x.Message)
.EmitWhen(x => x.Contains("emitted"))
.Create()
.ForTesting();
container.Assert(instance,
@"<?xml version=""1.0"" encoding=""utf-8""?><Issue530Tests-EmitMe xmlns=""clr-namespace:ExtendedXmlSerializer.Tests.ReportedIssues;assembly=ExtendedXmlSerializer.Tests.ReportedIssues""><Message>This is emitted</Message></Issue530Tests-EmitMe>");
}
sealed class Subject
{
public List<string> List { get; set; }
}
sealed class EmitMe
{
public string Message { get; set; }
public DoNotEmitMe NotEmitted { get; set; }
}
sealed class DoNotEmitMe
{
public string Message { get; set; }
}

Here it never emits a type, and only emits a member when it contains the string "emitted".

Thanks for the interesting tips, but I'm stuck on a problem. When I use EmitBehaviors.Classic with UseAutoFormatting and nullable values, empty strings are written, which leads to an exception when converting back to the empty value.

My simple test:

public static void Main(string[] args)
{

  var configuration = new ConfigurationContainer();
  configuration.UseAutoFormatting();
  configuration.Emit(EmitBehaviors.Classic);
  var testValue = new TestClass();
  testValue.ValueList = new List<double>();

  var serializer = configuration.Create();
  var serialized = serializer.Serialize(testValue);
  var desirialized = serializer.Deserialize<TestClass>(serialized);
}

class TestClass
{

  public double? Value1;

  public List<double> ValueList;

}

Thank you again for the great support!

No problem @imperiobadgo. This is actually a bug, as if the content is always emitted and it is null, we have no way of properly representing that in an XML attribute at present. We could get fancy and be like Xaml with a {x:Null}, but that would be far too disruptive/involved at this point.

In any case, I've updated UseAutoFormatting to account for FormatExceptions as well as empty strings to return null for Nullable<> converters and readers.

Check out this build and see how it treats you:
#531 (comment)

Btw I appreciate you using UseAutoFormatting, as it's one of the first extensions I ever wrote. ๐Ÿ˜

UseAutoFormatting just makes everything much more readable when you look into the XML. It also reduces the file size noticeably!

I will test your changes tomorrow and let you now, if i have any more problems ๐Ÿ˜

UseAutoFormatting just makes everything much more readable when you look into the XML. It also reduces the file size noticeably!

Nodding along @imperiobadgo. Sounds good about the testing. Let me know of any issues you find and I will look into them for you. ๐Ÿ‘

This fix has been deployed to NuGet:
https://www.nuget.org/packages/ExtendedXmlSerializer/

If you encounter any further issues please open a new issue and we'll take it from there. Closing this for now.

An extensible Xml Serializer for .NET that builds on the functionality of the classic XmlSerializer with a powerful and robust extension model.

I've only just managed to test your changes. But they work perfectly as expected! Thanks again!

Woohoo... glad to hear @imperiobadgo. Thank you for the confirmation. ๐Ÿ‘