Skip to content

Commit

Permalink
Do not serialize empty collections (#30)
Browse files Browse the repository at this point in the history
This is a temporary workaround before aaubry/YamlDotNet#608 gets merged.

This makes the YAML not contain bunch of rows like this:
```
variables: []
```
  • Loading branch information
premun committed May 17, 2021
1 parent 51e9f7f commit f3bbfd2
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
49 changes: 49 additions & 0 deletions src/Sharpliner/GraphTraversal/SharplinerGraphTraversalStrategy.cs
@@ -0,0 +1,49 @@
using YamlDotNet.Serialization;
using System.Collections.Generic;
using System.Collections;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;

namespace Sharpliner.GraphTraversal
{
/// <summary>
/// This is a workaround that skips empty collections and doesn't serialize them at all.
/// The proper way to do this is in a PR here: https://github.com/aaubry/YamlDotNet/pull/608
/// Before that is fixed, this is how we're going to do things (╯°□°)╯︵ ┻━┻
/// </summary>
public class SharplinerGraphTraversalStrategy : FullObjectGraphTraversalStrategy
{
private readonly ITypeInspector _typeDescriptor;

public SharplinerGraphTraversalStrategy(ITypeInspector typeDescriptor, ITypeResolver typeResolver, int maxRecursion, INamingConvention namingConvention)
: base(typeDescriptor, typeResolver, maxRecursion, namingConvention)
{
_typeDescriptor = typeDescriptor;
}

protected override void TraverseProperties<TContext>(IObjectDescriptor value, IObjectGraphVisitor<TContext> visitor, TContext context, Stack<ObjectPathSegment> path)
{
visitor.VisitMappingStart(value, typeof(string), typeof(object), context);

var source = value.NonNullValue();
foreach (var propertyDescriptor in _typeDescriptor.GetProperties(value.Type, source))
{
var propertyValue = propertyDescriptor.Read(source);

if (visitor.EnterMapping(propertyDescriptor, propertyValue, context))
{
// This is the actual change
if (propertyValue.Value is IEnumerable collection && !collection.GetEnumerator().MoveNext())
{
// Skip empty arrays/collections
continue;
}

Traverse(propertyDescriptor.Name, new ObjectDescriptor(propertyDescriptor.Name, typeof(string), typeof(string)), visitor, context, path);
Traverse(propertyDescriptor.Name, propertyValue, visitor, context, path);
}
}

visitor.VisitMappingEnd(value, context);
}
}
}
2 changes: 2 additions & 0 deletions src/Sharpliner/SharplinerSerializer.cs
@@ -1,5 +1,6 @@
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization;
using Sharpliner.GraphTraversal;

namespace Sharpliner.Definition
{
Expand All @@ -13,6 +14,7 @@ private static ISerializer InitializeSerializer()
{
var serializerBuilder = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.WithObjectGraphTraversalStrategyFactory((typeInspector, typeResolver, typeConverters, maximumRecursion) => new SharplinerGraphTraversalStrategy(typeInspector, typeResolver, maximumRecursion, CamelCaseNamingConvention.Instance))
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults);

return serializerBuilder.Build();
Expand Down
Expand Up @@ -65,7 +65,6 @@ public void Serialize_Pipeline_Test()
- name: AzureSubscription
value: Prod
- group: azure-prod
stages: []
");
}

Expand Down

0 comments on commit f3bbfd2

Please sign in to comment.