aaubry / YamlDotNet

YamlDotNet is a .NET library for YAML
MIT License
2.48k stars 466 forks source link

Disable serialization for specific types #862

Closed EdwardCooke closed 1 day ago

EdwardCooke commented 8 months ago

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 commented 1 month ago

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