Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions src/Verify.Tests/Serialization/SerializationSettingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
public class SerializationSettingsTests
{
[Fact]
public void ExtraConverterOverridesBuiltIn()
{
var converter = new CustomEnumConverter();
var settings = new SerializationSettings();
settings.AddExtraSettings(_ => _.Converters.Add(converter));

AssertUsesConverter(settings, converter);
AssertUsesConverter(new(settings), converter);
}

[Fact]
public void ExtraSettingsPreserveOrder()
{
var first = new CustomEnumConverter();
var second = new CustomEnumConverter();
var settings = new SerializationSettings();
settings.AddExtraSettings(
_ =>
{
_.Converters.Add(first);
_.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
});
settings.AddExtraSettings(
_ =>
{
Assert.Equal(ReferenceLoopHandling.Serialize, _.ReferenceLoopHandling);
_.Converters.Add(second);
_.ReferenceLoopHandling = ReferenceLoopHandling.Error;
});

AssertOrder(settings, first, second);
AssertOrder(new(settings), first, second);
}

[Fact]
public void ExplicitConverterPositionIsPreserved()
{
var first = new CustomEnumConverter();
var second = new CustomEnumConverter();
var settings = new SerializationSettings();
settings.AddExtraSettings(_ => _.Converters.Add(first));
settings.AddExtraSettings(_ => _.Converters.Insert(0, second));

AssertOrder(settings, second, first);
AssertOrder(new(settings), second, first);
}

[Fact]
public void RemovedConverterDoesNotAffectPriority()
{
var removed = new CustomEnumConverter();
var first = new CustomEnumConverter();
var second = new CustomEnumConverter();
var settings = new SerializationSettings();
settings.AddExtraSettings(_ => _.Converters.Add(removed));
settings.AddExtraSettings(_ => _.Converters.Add(first));
settings.AddExtraSettings(
_ =>
{
_.Converters.Remove(removed);
_.Converters.Add(second);
});

AssertOrder(settings, first, second);
AssertOrder(new(settings), first, second);
}

static void AssertOrder(SerializationSettings settings, JsonConverter first, JsonConverter second)
{
Assert.Same(first, settings.Serializer.Converters[0]);
Assert.Same(second, settings.Serializer.Converters[1]);
}

static void AssertUsesConverter(SerializationSettings settings, JsonConverter converter)
=> Assert.Same(converter, settings.Serializer.Converters[0]);

class CustomEnumConverter :
WriteOnlyJsonConverter<TestEnum>
{
public override void Write(VerifyJsonWriter writer, TestEnum value) =>
writer.WriteValue("custom");
}

enum TestEnum
{
Value
}
}
39 changes: 39 additions & 0 deletions src/Verify/Serialization/SerializationSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ partial class SerializationSettings
static CombinationResultsConverter combinationResultsConverter = new();

JsonSerializerSettings jsonSettings;
List<JsonConverter> builtInConverters = [];

public SerializationSettings()
{
Expand Down Expand Up @@ -132,6 +133,7 @@ JsonSerializerSettings BuildSettings()
converters.Add(stringDictionaryConverter);
converters.Add(keyValuePairConverter);
converters.Add(combinationResultsConverter);
builtInConverters = converters.ToList();
foreach (var extraSetting in extraSettings)
{
ApplyExtraSetting(settings, extraSetting);
Expand All @@ -154,6 +156,8 @@ void ApplyExtraSetting(JsonSerializerSettings settings, Action<JsonSerializerSet

action(settings);

PromoteExtraConverters(settings.Converters);

if (settings.DefaultValueHandling is null)
{
settings.DefaultValueHandling = current;
Expand All @@ -164,6 +168,41 @@ void ApplyExtraSetting(JsonSerializerSettings settings, Action<JsonSerializerSet
}
}

void PromoteExtraConverters(IList<JsonConverter> converters)
{
var remainingBuiltIns = builtInConverters.ToList();
var extras = new List<JsonConverter>();
var builtIns = new List<JsonConverter>();
foreach (var converter in converters)
{
var index = remainingBuiltIns.FindIndex(_ => ReferenceEquals(_, converter));
if (index < 0)
{
extras.Add(converter);
continue;
}

remainingBuiltIns.RemoveAt(index);
builtIns.Add(converter);
}

if (extras.Count == 0)
{
return;
}

converters.Clear();
foreach (var converter in extras)
{
converters.Add(converter);
}

foreach (var converter in builtIns)
{
converters.Add(converter);
}
}

public void AddExtraSettings(Action<JsonSerializerSettings> action)
{
extraSettings.Add(action);
Expand Down