diff --git a/src/Yamlify.SourceGenerator/YamlSourceGenerator.cs b/src/Yamlify.SourceGenerator/YamlSourceGenerator.cs
index 2ad407f..b465faf 100644
--- a/src/Yamlify.SourceGenerator/YamlSourceGenerator.cs
+++ b/src/Yamlify.SourceGenerator/YamlSourceGenerator.cs
@@ -1750,6 +1750,14 @@ private static void GenerateWriteMethod(StringBuilder sb, TypeToGenerate type, I
}
}
+ // Check for YamlIgnore with conditional conditions (WhenWritingNull, WhenWritingDefault)
+ var writeIgnoreCondition = GetWriteIgnoreCondition(prop);
+ if (writeIgnoreCondition == IgnoreCondition.Always)
+ {
+ // Already filtered out in the allProperties list, but double-check
+ continue;
+ }
+
// Check for sibling discriminator
// For dictionaries, we want sibling discriminator to apply to the dictionary values
// For regular lists/arrays, sibling discriminator doesn't make sense (each element should determine its own type)
@@ -1825,8 +1833,20 @@ private static void GenerateWriteMethod(StringBuilder sb, TypeToGenerate type, I
}
}
- // Wrap nullable properties with IgnoreNullValues and IgnoreEmptyObjects checks
- sb.AppendLine($" if (!options.IgnoreNullValues || ({string.Join(" && ", conditions)}))");
+ // Handle YamlIgnore conditions:
+ // - WhenWritingNull: Skip if null (property-level, always respected)
+ // - WhenWritingDefault: Skip if null (for nullable types, null is the default)
+ if (writeIgnoreCondition == IgnoreCondition.WhenWritingNull ||
+ writeIgnoreCondition == IgnoreCondition.WhenWritingDefault)
+ {
+ // Always skip if null, regardless of options.IgnoreNullValues
+ sb.AppendLine($" if ({string.Join(" && ", conditions)})");
+ }
+ else
+ {
+ // Wrap nullable properties with IgnoreNullValues and IgnoreEmptyObjects checks
+ sb.AppendLine($" if (!options.IgnoreNullValues || ({string.Join(" && ", conditions)}))");
+ }
sb.AppendLine(" {");
sb.AppendLine($" writer.WritePropertyName({propertyNameCode});");
GeneratePropertyWrite(sb, propName, prop.Type, allTypes, " ", siblingInfo);
@@ -1834,9 +1854,23 @@ private static void GenerateWriteMethod(StringBuilder sb, TypeToGenerate type, I
}
else
{
- // Non-nullable properties are always written
- sb.AppendLine($" writer.WritePropertyName({propertyNameCode});");
- GeneratePropertyWrite(sb, propName, prop.Type, allTypes, "", siblingInfo);
+ // Non-nullable properties - check for WhenWritingDefault
+ if (writeIgnoreCondition == IgnoreCondition.WhenWritingDefault)
+ {
+ // Skip if value equals default for the type
+ var defaultValue = GetDefaultValue(prop.Type);
+ sb.AppendLine($" if (!EqualityComparer<{prop.Type.ToDisplayString()}>.Default.Equals(value.{propName}, {defaultValue}))");
+ sb.AppendLine(" {");
+ sb.AppendLine($" writer.WritePropertyName({propertyNameCode});");
+ GeneratePropertyWrite(sb, propName, prop.Type, allTypes, " ", siblingInfo);
+ sb.AppendLine(" }");
+ }
+ else
+ {
+ // Non-nullable properties are always written
+ sb.AppendLine($" writer.WritePropertyName({propertyNameCode});");
+ GeneratePropertyWrite(sb, propName, prop.Type, allTypes, "", siblingInfo);
+ }
}
sb.AppendLine();
}
@@ -2537,18 +2571,74 @@ private static string GetYamlPropertyName(IPropertySymbol property)
return null;
}
- private static bool ShouldIgnoreProperty(IPropertySymbol property)
+ ///
+ /// Represents the YamlIgnoreCondition enum values from the runtime.
+ ///
+ private enum IgnoreCondition
+ {
+ Always = 0,
+ WhenWritingNull = 1,
+ WhenWritingDefault = 2,
+ Never = 3
+ }
+
+ ///
+ /// Gets the ignore condition for a property, or null if no YamlIgnore attribute is present.
+ ///
+ private static IgnoreCondition? GetIgnoreCondition(IPropertySymbol property)
{
- // Check for YamlIgnore attribute
foreach (var attr in property.GetAttributes())
{
if (attr.AttributeClass?.Name == "YamlIgnoreAttribute" ||
attr.AttributeClass?.ToDisplayString() == "Yamlify.Serialization.YamlIgnoreAttribute")
{
- return true;
+ // Check for the Condition named argument
+ foreach (var namedArg in attr.NamedArguments)
+ {
+ if (namedArg.Key == "Condition" && namedArg.Value.Value is int conditionValue)
+ {
+ return (IgnoreCondition)conditionValue;
+ }
+ }
+ // Default is Always if Condition is not specified
+ return IgnoreCondition.Always;
}
}
- return false;
+ return null;
+ }
+
+ ///
+ /// Determines if a property should be ignored during deserialization (reading).
+ /// Only properties with YamlIgnore(Condition = Always) are ignored during reading.
+ /// Properties with WhenWritingNull/WhenWritingDefault are still read but may be skipped during writing.
+ ///
+ private static bool ShouldIgnorePropertyForReading(IPropertySymbol property)
+ {
+ var condition = GetIgnoreCondition(property);
+ return condition == IgnoreCondition.Always;
+ }
+
+ ///
+ /// Determines if a property should be ignored during serialization (writing).
+ /// Returns the ignore condition, or null if the property should always be written.
+ ///
+ private static IgnoreCondition? GetWriteIgnoreCondition(IPropertySymbol property)
+ {
+ var condition = GetIgnoreCondition(property);
+ if (condition == IgnoreCondition.Never)
+ {
+ return null; // Never ignore = always write
+ }
+ return condition;
+ }
+
+ ///
+ /// Legacy method for backward compatibility - use ShouldIgnorePropertyForReading for reading.
+ ///
+ private static bool ShouldIgnoreProperty(IPropertySymbol property)
+ {
+ // For reading, only ignore if condition is Always
+ return ShouldIgnorePropertyForReading(property);
}
private static int GetPropertyOrder(IPropertySymbol property)
diff --git a/test/Yamlify.Tests/Serialization/YamlIgnoreConditionTests.cs b/test/Yamlify.Tests/Serialization/YamlIgnoreConditionTests.cs
new file mode 100644
index 0000000..4791d81
--- /dev/null
+++ b/test/Yamlify.Tests/Serialization/YamlIgnoreConditionTests.cs
@@ -0,0 +1,693 @@
+using Yamlify;
+using Yamlify.Serialization;
+
+namespace Yamlify.Tests.Serialization;
+
+///
+/// Tests for YamlIgnore attribute with different YamlIgnoreCondition values.
+///
+public class YamlIgnoreConditionTests
+{
+ #region YamlIgnoreCondition.Always Tests
+
+ [Fact]
+ public void Serialize_PropertyWithIgnoreAlways_PropertyNotWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreAlways
+ {
+ Name = "Test",
+ AlwaysIgnored = "Should not appear",
+ Value = 42
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreAlways);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("value: 42", yaml);
+ Assert.DoesNotContain("always-ignored:", yaml);
+ Assert.DoesNotContain("Should not appear", yaml);
+ }
+
+ [Fact]
+ public void Deserialize_PropertyWithIgnoreAlways_PropertyNotRead()
+ {
+ // Arrange
+ const string yaml = """
+ name: Test
+ always-ignored: This value exists in yaml
+ value: 42
+ """;
+
+ // Act
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreAlways);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Null(result.AlwaysIgnored); // Should remain default (null)
+ Assert.Equal(42, result.Value);
+ }
+
+ [Fact]
+ public void RoundTrip_PropertyWithIgnoreAlways_PropertyLost()
+ {
+ // Arrange
+ var original = new ClassWithIgnoreAlways
+ {
+ Name = "Test",
+ AlwaysIgnored = "This will be lost",
+ Value = 42
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(original, YamlIgnoreConditionContext.Default.ClassWithIgnoreAlways);
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreAlways);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Null(result.AlwaysIgnored); // Lost during round trip
+ Assert.Equal(42, result.Value);
+ }
+
+ #endregion
+
+ #region YamlIgnoreCondition.WhenWritingNull Tests
+
+ [Fact]
+ public void Serialize_PropertyWithWhenWritingNull_NullValue_PropertyNotWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreWhenWritingNull
+ {
+ Name = "Test",
+ OptionalValue = null,
+ RequiredValue = 42
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingNull);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("required-value: 42", yaml);
+ Assert.DoesNotContain("optional-value:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_PropertyWithWhenWritingNull_NonNullValue_PropertyWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreWhenWritingNull
+ {
+ Name = "Test",
+ OptionalValue = "Has a value",
+ RequiredValue = 42
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingNull);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("optional-value: Has a value", yaml);
+ Assert.Contains("required-value: 42", yaml);
+ }
+
+ [Fact]
+ public void Deserialize_PropertyWithWhenWritingNull_PropertyPresent_PropertyRead()
+ {
+ // Arrange - WhenWritingNull only affects writing, not reading
+ const string yaml = """
+ name: Test
+ optional-value: Value from YAML
+ required-value: 42
+ """;
+
+ // Act
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingNull);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Equal("Value from YAML", result.OptionalValue);
+ Assert.Equal(42, result.RequiredValue);
+ }
+
+ [Fact]
+ public void RoundTrip_PropertyWithWhenWritingNull_NonNullValue_Preserved()
+ {
+ // Arrange
+ var original = new ClassWithIgnoreWhenWritingNull
+ {
+ Name = "Test",
+ OptionalValue = "Keep this",
+ RequiredValue = 42
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(original, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingNull);
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingNull);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Equal("Keep this", result.OptionalValue);
+ Assert.Equal(42, result.RequiredValue);
+ }
+
+ [Fact]
+ public void Serialize_NullableBoolWithWhenWritingNull_NullValue_PropertyNotWritten()
+ {
+ // Arrange
+ var obj = new ClassWithNullableBoolIgnoreWhenNull
+ {
+ Name = "Test",
+ OptionalFlag = null
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithNullableBoolIgnoreWhenNull);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("optional-flag:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_NullableBoolWithWhenWritingNull_FalseValue_PropertyWritten()
+ {
+ // Arrange - false is not null, so it should be written
+ var obj = new ClassWithNullableBoolIgnoreWhenNull
+ {
+ Name = "Test",
+ OptionalFlag = false
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithNullableBoolIgnoreWhenNull);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("optional-flag: false", yaml);
+ }
+
+ [Fact]
+ public void Serialize_NullableBoolWithWhenWritingNull_TrueValue_PropertyWritten()
+ {
+ // Arrange
+ var obj = new ClassWithNullableBoolIgnoreWhenNull
+ {
+ Name = "Test",
+ OptionalFlag = true
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithNullableBoolIgnoreWhenNull);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("optional-flag: true", yaml);
+ }
+
+ #endregion
+
+ #region YamlIgnoreCondition.WhenWritingDefault Tests
+
+ [Fact]
+ public void Serialize_IntWithWhenWritingDefault_ZeroValue_PropertyNotWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreWhenWritingDefault
+ {
+ Name = "Test",
+ Counter = 0 // default for int
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("counter:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_IntWithWhenWritingDefault_NonZeroValue_PropertyWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreWhenWritingDefault
+ {
+ Name = "Test",
+ Counter = 5
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("counter: 5", yaml);
+ }
+
+ [Fact]
+ public void Serialize_BoolWithWhenWritingDefault_FalseValue_PropertyNotWritten()
+ {
+ // Arrange
+ var obj = new ClassWithBoolIgnoreWhenDefault
+ {
+ Name = "Test",
+ IsEnabled = false // default for bool
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithBoolIgnoreWhenDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("is-enabled:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_BoolWithWhenWritingDefault_TrueValue_PropertyWritten()
+ {
+ // Arrange
+ var obj = new ClassWithBoolIgnoreWhenDefault
+ {
+ Name = "Test",
+ IsEnabled = true
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithBoolIgnoreWhenDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("is-enabled: true", yaml);
+ }
+
+ [Fact]
+ public void Serialize_StringWithWhenWritingDefault_NullValue_PropertyNotWritten()
+ {
+ // Arrange - default for string? is null
+ var obj = new ClassWithStringIgnoreWhenDefault
+ {
+ Name = "Test",
+ Description = null
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithStringIgnoreWhenDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("description:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_StringWithWhenWritingDefault_EmptyString_PropertyWritten()
+ {
+ // Arrange - empty string is not null (the default), so it should be written
+ var obj = new ClassWithStringIgnoreWhenDefault
+ {
+ Name = "Test",
+ Description = ""
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithStringIgnoreWhenDefault);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("description:", yaml);
+ }
+
+ [Fact]
+ public void Deserialize_PropertyWithWhenWritingDefault_PropertyPresent_PropertyRead()
+ {
+ // Arrange - WhenWritingDefault only affects writing, not reading
+ const string yaml = """
+ name: Test
+ counter: 0
+ """;
+
+ // Act
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreWhenWritingDefault);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Equal(0, result.Counter);
+ }
+
+ #endregion
+
+ #region YamlIgnoreCondition.Never Tests
+
+ [Fact]
+ public void Serialize_PropertyWithIgnoreNever_NullValue_PropertyWritten()
+ {
+ // Arrange - Never means always write, even if null
+ var obj = new ClassWithIgnoreNever
+ {
+ Name = "Test",
+ AlwaysWritten = null
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreNever);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("always-written:", yaml);
+ }
+
+ [Fact]
+ public void Serialize_PropertyWithIgnoreNever_NonNullValue_PropertyWritten()
+ {
+ // Arrange
+ var obj = new ClassWithIgnoreNever
+ {
+ Name = "Test",
+ AlwaysWritten = "Has a value"
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithIgnoreNever);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.Contains("always-written: Has a value", yaml);
+ }
+
+ [Fact]
+ public void Deserialize_PropertyWithIgnoreNever_PropertyPresent_PropertyRead()
+ {
+ // Arrange
+ const string yaml = """
+ name: Test
+ always-written: Value from YAML
+ """;
+
+ // Act
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.ClassWithIgnoreNever);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("Test", result.Name);
+ Assert.Equal("Value from YAML", result.AlwaysWritten);
+ }
+
+ #endregion
+
+ #region Legacy Migration Scenario Tests
+
+ [Fact]
+ public void Deserialize_LegacyProperty_WithWhenWritingNull_PropertyRead()
+ {
+ // Arrange - Simulates reading a legacy YAML format
+ const string yaml = """
+ name: my-feature
+ legacy-enabled: true
+ """;
+
+ // Act
+ var result = YamlSerializer.Deserialize(yaml, YamlIgnoreConditionContext.Default.FeatureConfig);
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("my-feature", result.Name);
+ Assert.True(result.LegacyEnabled); // Should be read from YAML
+ }
+
+ [Fact]
+ public void Serialize_LegacyProperty_WithWhenWritingNull_WhenNull_PropertyNotWritten()
+ {
+ // Arrange - Legacy property is null (not migrated or already migrated)
+ var obj = new FeatureConfig
+ {
+ Name = "my-feature",
+ LegacyEnabled = null,
+ Settings = new FeatureConfigSettings { Enabled = true }
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.FeatureConfig);
+
+ // Assert
+ Assert.Contains("name: my-feature", yaml);
+ Assert.Contains("settings:", yaml);
+ Assert.Contains("enabled: true", yaml);
+ Assert.DoesNotContain("legacy-enabled:", yaml); // Should not be written
+ }
+
+ [Fact]
+ public void RoundTrip_LegacyPropertyRead_ThenNotWritten()
+ {
+ // Arrange - Simulates reading legacy YAML
+ const string legacyYaml = """
+ name: my-feature
+ legacy-enabled: false
+ """;
+
+ // Act - Read the legacy format
+ var config = YamlSerializer.Deserialize(legacyYaml, YamlIgnoreConditionContext.Default.FeatureConfig);
+
+ // Simulate migration: use legacy value to populate new format, then clear legacy
+ if (config != null && config.LegacyEnabled.HasValue)
+ {
+ config.Settings = new FeatureConfigSettings { Enabled = config.LegacyEnabled.Value };
+ config.LegacyEnabled = null;
+ }
+
+ // Serialize back
+ var newYaml = YamlSerializer.Serialize(config!, YamlIgnoreConditionContext.Default.FeatureConfig);
+
+ // Assert - Legacy property should not appear in output
+ Assert.Contains("name: my-feature", newYaml);
+ Assert.Contains("settings:", newYaml);
+ Assert.Contains("enabled: false", newYaml);
+ Assert.DoesNotContain("legacy-enabled:", newYaml);
+ }
+
+ #endregion
+
+ #region Multiple Conditions on Different Properties
+
+ [Fact]
+ public void Serialize_MixedConditions_CorrectPropertiesWritten()
+ {
+ // Arrange
+ var obj = new ClassWithMixedConditions
+ {
+ Name = "Test",
+ AlwaysIgnored = "should not appear",
+ NullIgnored = null,
+ DefaultIgnored = 0,
+ NeverIgnored = null
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithMixedConditions);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("always-ignored:", yaml); // Always ignored
+ Assert.DoesNotContain("null-ignored:", yaml); // WhenWritingNull + null value
+ Assert.DoesNotContain("default-ignored:", yaml); // WhenWritingDefault + 0
+ Assert.Contains("never-ignored:", yaml); // Never - always written even when null
+ }
+
+ [Fact]
+ public void Serialize_MixedConditions_AllNonDefault_AllWritten()
+ {
+ // Arrange
+ var obj = new ClassWithMixedConditions
+ {
+ Name = "Test",
+ AlwaysIgnored = "still ignored",
+ NullIgnored = "has value",
+ DefaultIgnored = 5,
+ NeverIgnored = "has value"
+ };
+
+ // Act
+ var yaml = YamlSerializer.Serialize(obj, YamlIgnoreConditionContext.Default.ClassWithMixedConditions);
+
+ // Assert
+ Assert.Contains("name: Test", yaml);
+ Assert.DoesNotContain("always-ignored:", yaml); // Still ignored
+ Assert.Contains("null-ignored: has value", yaml); // Written because not null
+ Assert.Contains("default-ignored: 5", yaml); // Written because not default
+ Assert.Contains("never-ignored: has value", yaml); // Always written
+ }
+
+ #endregion
+}
+
+#region Test Models
+
+///
+/// Class with YamlIgnore(Condition = Always) - property completely ignored.
+///
+public class ClassWithIgnoreAlways
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("always-ignored")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.Always)]
+ public string? AlwaysIgnored { get; set; }
+
+ public int Value { get; set; }
+}
+
+///
+/// Class with YamlIgnore(Condition = WhenWritingNull) - only ignored during serialization when null.
+///
+public class ClassWithIgnoreWhenWritingNull
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("optional-value")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingNull)]
+ public string? OptionalValue { get; set; }
+
+ [YamlPropertyName("required-value")]
+ public int RequiredValue { get; set; }
+}
+
+///
+/// Class with nullable bool and WhenWritingNull condition.
+///
+public class ClassWithNullableBoolIgnoreWhenNull
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("optional-flag")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingNull)]
+ public bool? OptionalFlag { get; set; }
+}
+
+///
+/// Class with YamlIgnore(Condition = WhenWritingDefault) on an int property.
+///
+public class ClassWithIgnoreWhenWritingDefault
+{
+ public string? Name { get; set; }
+
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingDefault)]
+ public int Counter { get; set; }
+}
+
+///
+/// Class with YamlIgnore(Condition = WhenWritingDefault) on a bool property.
+///
+public class ClassWithBoolIgnoreWhenDefault
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("is-enabled")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingDefault)]
+ public bool IsEnabled { get; set; }
+}
+
+///
+/// Class with YamlIgnore(Condition = WhenWritingDefault) on a string property.
+///
+public class ClassWithStringIgnoreWhenDefault
+{
+ public string? Name { get; set; }
+
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingDefault)]
+ public string? Description { get; set; }
+}
+
+///
+/// Class with YamlIgnore(Condition = Never) - always written even when null.
+///
+public class ClassWithIgnoreNever
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("always-written")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.Never)]
+ public string? AlwaysWritten { get; set; }
+}
+
+///
+/// Simulates a legacy migration scenario where a property is read but not written back.
+///
+public class FeatureConfig
+{
+ public string? Name { get; set; }
+
+ ///
+ /// Legacy property - read from old YAML but not written back.
+ ///
+ [YamlPropertyName("legacy-enabled")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingNull)]
+ public bool? LegacyEnabled { get; set; }
+
+ ///
+ /// New format settings object.
+ ///
+ public FeatureConfigSettings? Settings { get; set; }
+}
+
+///
+/// Settings object for the new format.
+///
+public class FeatureConfigSettings
+{
+ public bool Enabled { get; set; }
+}
+
+///
+/// Class with different YamlIgnoreCondition values on different properties.
+///
+public class ClassWithMixedConditions
+{
+ public string? Name { get; set; }
+
+ [YamlPropertyName("always-ignored")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.Always)]
+ public string? AlwaysIgnored { get; set; }
+
+ [YamlPropertyName("null-ignored")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingNull)]
+ public string? NullIgnored { get; set; }
+
+ [YamlPropertyName("default-ignored")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.WhenWritingDefault)]
+ public int DefaultIgnored { get; set; }
+
+ [YamlPropertyName("never-ignored")]
+ [YamlIgnore(Condition = YamlIgnoreCondition.Never)]
+ public string? NeverIgnored { get; set; }
+}
+
+#endregion
+
+#region Serializer Context
+
+///
+/// Serializer context with IgnoreNullValues disabled to properly test YamlIgnoreCondition.
+///
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+[YamlSerializable]
+public partial class YamlIgnoreConditionContext : YamlSerializerContext
+{
+}
+
+#endregion