YamlDotNet icon indicating copy to clipboard operation
YamlDotNet copied to clipboard

Disable serialization for specific types

Open EdwardCooke opened this issue 1 year ago • 1 comments

Discussed in https://github.com/aaubry/YamlDotNet/discussions/861

Originally posted by JamesTheButler October 30, 2023 Hi everyone!

I am serializing a class that contains a public Action field. Consider the following example:

record class Example
{
  public int Int { get; private set; }

  public Action? SomeAction;
};

public void Test()
{
  var serializer = new SerializerBuilder().Build();
  var output = serializer.Serialize(new DemoClass());
  // output:
  //  SomeAction: 
  //  Int: 0
}

SomeAction gets serialized to an empty string in yaml, which is a bit annoying but still okay. It get's fun if we actually subscribe to SomeAction when the serializer generates ~5.000 lines of yaml to describe the attached action.

Is it possible to not serialize members of a given type? I know about [YamlIgnore] but I would rather set up my serializer to ignore all members of the type Action (and possibly other types as well) in any of my serializable classes.

EdwardCooke avatar Oct 30 '23 13:10 EdwardCooke

You can do this with a custom type inspector.

using YamlDotNet.Serialization;
using YamlDotNet.Serialization.TypeInspectors;

var data = new Receiver();

var serializer = new SerializerBuilder()
    .WithTypeInspector(inner=>new IgnoreTypeTypeInspector(inner), where=>where.OnBottom())
    .Build();
var yaml = serializer.Serialize(data);
Console.WriteLine(yaml);

public class IgnoreTypeTypeInspector : TypeInspectorSkeleton
{
    private readonly ITypeInspector innerTypeDescriptor;

    public IgnoreTypeTypeInspector(ITypeInspector innerTypeDescriptor)
    {
        this.innerTypeDescriptor = innerTypeDescriptor ?? throw new ArgumentNullException(nameof(innerTypeDescriptor));
    }

    public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object? container)
    {
        var properties = innerTypeDescriptor.GetProperties(type, container)
            .Where(p => p.Type != typeof(int));
        return properties;
    }
}

public class Receiver
{
    public string ReceiverType = Guid.NewGuid().ToString();
    public string ReceiverName = Guid.NewGuid().ToString();
    public int IgnoreMyIntType = 0;
}

Results in

ReceiverType: 24329920-d193-4e5b-b849-1b033e46c3a6
ReceiverName: f9e33caa-86e3-4c12-8931-ec303a74b59f

EdwardCooke avatar May 11 '24 17:05 EdwardCooke