-
-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #475 from gregsdennis/yaml/add-serializer
add yaml serializer to mimic json serializer (somewhat)
- Loading branch information
Showing
6 changed files
with
271 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
StringProp: string | ||
IntProp: 42 | ||
DecimalProp: 42.5 | ||
DoubleProp: 42.9 | ||
BoolProp: true | ||
ListOfInts: | ||
- 1 | ||
- 2 | ||
- 3 | ||
- 4 | ||
MapOfStrings: | ||
string1: found | ||
string2: lost | ||
NestedObject: | ||
OtherString: yep |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
using NUnit.Framework; | ||
// ReSharper disable NonReadonlyMemberInGetHashCode | ||
#pragma warning disable NUnit2005 | ||
#pragma warning disable CS8618 | ||
|
||
namespace Yaml2JsonNode.Tests; | ||
|
||
public class SerializerTests | ||
{ | ||
private class Bar | ||
{ | ||
public string OtherString { get; set; } | ||
|
||
protected bool Equals(Bar other) | ||
{ | ||
return OtherString == other.OtherString; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if (ReferenceEquals(null, obj)) return false; | ||
if (ReferenceEquals(this, obj)) return true; | ||
if (obj.GetType() != this.GetType()) return false; | ||
return Equals((Bar)obj); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return OtherString.GetHashCode(); | ||
} | ||
} | ||
|
||
private class Foo | ||
{ | ||
public string StringProp { get; set; } | ||
public int IntProp { get; set; } | ||
public decimal DecimalProp { get; set; } | ||
public double DoubleProp { get; set; } | ||
public bool BoolProp { get; set; } | ||
public List<int> ListOfInts { get; set; } | ||
public Dictionary<string, string> MapOfStrings { get; set; } | ||
public Bar NestedObject { get; set; } | ||
|
||
protected bool Equals(Foo other) | ||
{ | ||
var listEqual = ListOfInts.Zip(other.ListOfInts) | ||
.All(x => x.First == x.Second); | ||
var joinedMap = MapOfStrings.Join(other.MapOfStrings, | ||
x => x.Key, | ||
y => y.Key, | ||
(x, y) => x.Value == y.Value) | ||
.ToList(); | ||
var mapEqual = joinedMap.Count == MapOfStrings.Count && joinedMap.All(x => x); | ||
|
||
return StringProp == other.StringProp && | ||
IntProp == other.IntProp && | ||
DecimalProp == other.DecimalProp && | ||
DoubleProp.Equals(other.DoubleProp) && | ||
BoolProp == other.BoolProp && | ||
listEqual && | ||
mapEqual && | ||
NestedObject.Equals(other.NestedObject); | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if (ReferenceEquals(null, obj)) return false; | ||
if (ReferenceEquals(this, obj)) return true; | ||
if (obj.GetType() != this.GetType()) return false; | ||
return Equals((Foo)obj); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return HashCode.Combine(StringProp, IntProp, DecimalProp, DoubleProp, BoolProp, ListOfInts, MapOfStrings, NestedObject); | ||
} | ||
} | ||
|
||
[Test] | ||
public void SerializeObject() | ||
{ | ||
var foo = new Foo | ||
{ | ||
StringProp = "string", | ||
IntProp = 42, | ||
DecimalProp = 42.5m, | ||
DoubleProp = 42.9, | ||
BoolProp = true, | ||
ListOfInts = new List<int> { 1, 2, 3, 4 }, | ||
MapOfStrings = new Dictionary<string, string> | ||
{ | ||
["string1"] = "found", | ||
["string2"] = "lost" | ||
}, | ||
NestedObject = new Bar | ||
{ | ||
OtherString = "yep" | ||
} | ||
}; | ||
|
||
var path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "Files", "expected-serialized.yaml") | ||
.AdjustForPlatform(); | ||
|
||
var expected = File.ReadAllText(path); | ||
|
||
var actual = YamlSerializer.Serialize(foo); | ||
|
||
Assert.AreEqual(expected, actual); | ||
} | ||
|
||
[Test] | ||
public void DeserializeObject() | ||
{ | ||
var path = Path.Combine(TestContext.CurrentContext.WorkDirectory, "Files", "expected-serialized.yaml") | ||
.AdjustForPlatform(); | ||
|
||
var text = File.ReadAllText(path); | ||
|
||
var expected = new Foo | ||
{ | ||
StringProp = "string", | ||
IntProp = 42, | ||
DecimalProp = 42.5m, | ||
DoubleProp = 42.9, | ||
BoolProp = true, | ||
ListOfInts = new List<int> { 1, 2, 3, 4 }, | ||
MapOfStrings = new Dictionary<string, string> | ||
{ | ||
["string1"] = "found", | ||
["string2"] = "lost" | ||
}, | ||
NestedObject = new Bar | ||
{ | ||
OtherString = "yep" | ||
} | ||
}; | ||
|
||
|
||
var actual = YamlSerializer.Deserialize<Foo>(text); | ||
|
||
Assert.AreEqual(expected, actual); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
using System; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text.Json; | ||
using YamlDotNet.RepresentationModel; | ||
using YamlDotNet.Serialization; | ||
|
||
namespace Yaml2JsonNode; | ||
|
||
/// <summary> | ||
/// Provides common serializer functionality. | ||
/// </summary> | ||
public static class YamlSerializer | ||
{ | ||
/// <summary> | ||
/// Serializes an object to a YAML string | ||
/// </summary> | ||
/// <typeparam name="T">The type of the object.</typeparam> | ||
/// <param name="obj">The object.</param> | ||
/// <param name="options">(optional) JSON serializer options.</param> | ||
/// <param name="configure">(optional) YAML serializer configuration method.</param> | ||
/// <returns>The YAML string.</returns> | ||
public static string Serialize<T>(T obj, JsonSerializerOptions? options = null, Action<SerializerBuilder>? configure = null) | ||
{ | ||
var json = JsonSerializer.SerializeToNode(obj, options); | ||
var yaml = json!.ToYamlNode(); | ||
|
||
return Serialize(yaml, configure); | ||
} | ||
|
||
/// <summary> | ||
/// Serializes a YAML stream (a collection of documents) to a string. | ||
/// </summary> | ||
/// <param name="yaml">The stream.</param> | ||
/// <param name="configure">(optional) YAML serializer configuration method.</param> | ||
/// <returns>The YAML string.</returns> | ||
public static string Serialize(YamlStream yaml, Action<SerializerBuilder>? configure = null) | ||
{ | ||
var builder = new SerializerBuilder(); | ||
|
||
configure?.Invoke(builder); | ||
|
||
var serializer = builder.Build(); | ||
|
||
using var writer = new StringWriter(); | ||
|
||
foreach (var document in yaml.Documents) | ||
{ | ||
serializer.Serialize(writer, document.RootNode); | ||
} | ||
|
||
return writer.ToString(); | ||
} | ||
|
||
/// <summary> | ||
/// Serializes a YAML document to a string. | ||
/// </summary> | ||
/// <param name="yaml">The document.</param> | ||
/// <param name="configure">(optional) YAML serializer configuration method.</param> | ||
/// <returns>The YAML string.</returns> | ||
public static string Serialize(YamlDocument yaml, Action<SerializerBuilder>? configure = null) | ||
{ | ||
return Serialize(new YamlStream(yaml), configure); | ||
} | ||
|
||
/// <summary> | ||
/// Serializes a YAML node to a string | ||
/// </summary> | ||
/// <param name="yaml">The node.</param> | ||
/// <param name="configure">(optional) YAML serializer configuration method.</param> | ||
/// <returns>The YAML string.</returns> | ||
public static string Serialize(YamlNode yaml, Action<SerializerBuilder>? configure = null) | ||
{ | ||
return Serialize(new YamlDocument(yaml), configure); | ||
} | ||
|
||
/// <summary> | ||
/// Deserializes the first YAML document found in text to an object. | ||
/// </summary> | ||
/// <typeparam name="T">The type of the object.</typeparam> | ||
/// <param name="yamlText">The YAML text.</param> | ||
/// <param name="options"></param> | ||
/// <returns>The object or null.</returns> | ||
public static T? Deserialize<T>(string yamlText, JsonSerializerOptions? options = null) | ||
{ | ||
var yaml = Parse(yamlText).First(); | ||
var json = yaml.ToJsonNode(); | ||
|
||
return json.Deserialize<T>(options); | ||
} | ||
|
||
/// <summary> | ||
/// Parses YAML text into a stream (collection of documents). | ||
/// </summary> | ||
/// <param name="yamlText">The YAML text.</param> | ||
/// <returns>A YAML stream representing the content of the text.</returns> | ||
public static YamlStream Parse(string yamlText) | ||
{ | ||
using var reader = new StringReader(yamlText); | ||
var yamlStream = new YamlStream(); | ||
yamlStream.Load(reader); | ||
return yamlStream; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters