-
-
Notifications
You must be signed in to change notification settings - Fork 491
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 #930 from MrLuje/fsharp-option
Add FSharpOption support +semver:feature
- Loading branch information
Showing
9 changed files
with
342 additions
and
9 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,87 @@ | ||
module DeserializerTests | ||
|
||
open System | ||
open Xunit | ||
open YamlDotNet.Serialization | ||
open YamlDotNet.Serialization.NamingConventions | ||
open FsUnit.Xunit | ||
open System.ComponentModel | ||
|
||
[<CLIMutable>] | ||
type Spec = { | ||
EngineType: string | ||
DriveType: string | ||
} | ||
|
||
[<CLIMutable>] | ||
type Car = { | ||
Name: string | ||
Year: int | ||
Spec: Spec option | ||
Nickname: string option | ||
} | ||
|
||
[<CLIMutable>] | ||
type Person = { | ||
Name: string | ||
MomentOfBirth: DateTime | ||
Cars: Car array | ||
} | ||
|
||
[<Fact>] | ||
let Deserialize_YamlWithScalarOptions() = | ||
let yaml = """ | ||
name: Jack | ||
momentOfBirth: 1983-04-21T20:21:03.0041599Z | ||
cars: | ||
- name: Mercedes | ||
year: 2018 | ||
nickname: Jessy | ||
- name: Honda | ||
year: 2021 | ||
""" | ||
let sut = DeserializerBuilder() | ||
.WithNamingConvention(CamelCaseNamingConvention.Instance) | ||
.Build() | ||
|
||
let person = sut.Deserialize<Person>(yaml) | ||
person.Name |> should equal "Jack" | ||
person.Cars |> should haveLength 2 | ||
person.Cars[0].Name |> should equal "Mercedes" | ||
person.Cars[0].Nickname |> should equal (Some "Jessy") | ||
person.Cars[1].Name |> should equal "Honda" | ||
person.Cars[1].Nickname |> should equal None | ||
|
||
|
||
[<Fact>] | ||
let Deserialize_YamlWithObjectOptions() = | ||
let yaml = """ | ||
name: Jack | ||
momentOfBirth: 1983-04-21T20:21:03.0041599Z | ||
cars: | ||
- name: Mercedes | ||
year: 2018 | ||
spec: | ||
engineType: V6 | ||
driveType: AWD | ||
- name: Honda | ||
year: 2021 | ||
""" | ||
let sut = DeserializerBuilder() | ||
.WithNamingConvention(CamelCaseNamingConvention.Instance) | ||
.Build() | ||
|
||
let person = sut.Deserialize<Person>(yaml) | ||
person.Name |> should equal "Jack" | ||
person.Cars |> should haveLength 2 | ||
|
||
person.Cars[0].Name |> should equal "Mercedes" | ||
person.Cars[0].Spec |> should not' (be null) | ||
person.Cars[0].Spec |> Option.isSome |> should equal true | ||
person.Cars[0].Spec.Value.EngineType |> should equal "V6" | ||
person.Cars[0].Spec.Value.DriveType |> should equal "AWD" | ||
|
||
person.Cars[1].Name |> should equal "Honda" | ||
person.Cars[1].Spec |> should be null | ||
person.Cars[1].Spec |> should equal None | ||
person.Cars[1].Nickname |> should equal None |
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,152 @@ | ||
module SerializerTests | ||
|
||
open System | ||
open Xunit | ||
open YamlDotNet.Serialization | ||
open YamlDotNet.Serialization.NamingConventions | ||
open FsUnit.Xunit | ||
open YamlDotNet.Core | ||
|
||
[<CLIMutable>] | ||
type Spec = { | ||
EngineType: string | ||
DriveType: string | ||
} | ||
|
||
[<CLIMutable>] | ||
type Car = { | ||
Name: string | ||
Year: int | ||
Spec: Spec option | ||
Nickname: string option | ||
} | ||
|
||
[<CLIMutable>] | ||
type Person = { | ||
Name: string | ||
MomentOfBirth: DateTime | ||
KidsSeat: int option | ||
Cars: Car array | ||
} | ||
|
||
[<Fact>] | ||
let Serialize_YamlWithScalarOptions() = | ||
let jackTheDriver = { | ||
Name = "Jack" | ||
MomentOfBirth = DateTime(1983, 4, 21, 20, 21, 03, 4) | ||
KidsSeat = Some 1 | ||
Cars = [| | ||
{ Name = "Mercedes" | ||
Year = 2018 | ||
Nickname = Some "Jessy" | ||
Spec = None }; | ||
{ Name = "Honda" | ||
Year = 2021 | ||
Nickname = None | ||
Spec = None } | ||
|] | ||
} | ||
|
||
let yaml = """name: Jack | ||
momentOfBirth: 1983-04-21T20:21:03.0040000 | ||
kidsSeat: 1 | ||
cars: | ||
- name: Mercedes | ||
year: 2018 | ||
spec: | ||
nickname: Jessy | ||
- name: Honda | ||
year: 2021 | ||
spec: | ||
nickname: | ||
""" | ||
let sut = SerializerBuilder() | ||
.WithNamingConvention(CamelCaseNamingConvention.Instance) | ||
.Build() | ||
|
||
let person = sut.Serialize(jackTheDriver) | ||
person |> should equal yaml | ||
|
||
|
||
[<Fact>] | ||
let Serialize_YamlWithScalarOptions_OmitNull() = | ||
let jackTheDriver = { | ||
Name = "Jack" | ||
MomentOfBirth = DateTime(1983, 4, 21, 20, 21, 03, 4) | ||
KidsSeat = Some 1 | ||
Cars = [| | ||
{ Name = "Mercedes" | ||
Year = 2018 | ||
Nickname = Some "Jessy" | ||
Spec = None }; | ||
{ Name = "Honda" | ||
Year = 2021 | ||
Nickname = None | ||
Spec = None } | ||
|] | ||
} | ||
|
||
let yaml = """name: Jack | ||
momentOfBirth: 1983-04-21T20:21:03.0040000 | ||
kidsSeat: 1 | ||
cars: | ||
- name: Mercedes | ||
year: 2018 | ||
nickname: Jessy | ||
- name: Honda | ||
year: 2021 | ||
""" | ||
let sut = SerializerBuilder() | ||
.WithNamingConvention(CamelCaseNamingConvention.Instance) | ||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull) | ||
.Build() | ||
|
||
let person = sut.Serialize(jackTheDriver) | ||
person |> should equal yaml | ||
|
||
|
||
[<Fact>] | ||
let Serialize_YamlWithObjectOptions_OmitNull() = | ||
let jackTheDriver = { | ||
Name = "Jack" | ||
MomentOfBirth = DateTime(1983, 4, 21, 20, 21, 03, 4) | ||
KidsSeat = Some 1 | ||
Cars = [| | ||
{ Name = "Mercedes" | ||
Year = 2018 | ||
Nickname = None | ||
Spec = Some { | ||
EngineType = "V6" | ||
DriveType = "AWD" | ||
} }; | ||
{ Name = "Honda" | ||
Year = 2021 | ||
Nickname = None | ||
Spec = None } | ||
|] | ||
} | ||
|
||
let yaml = """name: Jack | ||
momentOfBirth: 1983-04-21T20:21:03.0040000 | ||
kidsSeat: 1 | ||
cars: | ||
- name: Mercedes | ||
year: 2018 | ||
spec: | ||
engineType: V6 | ||
driveType: AWD | ||
- name: Honda | ||
year: 2021 | ||
""" | ||
let sut = SerializerBuilder() | ||
.WithNamingConvention(CamelCaseNamingConvention.Instance) | ||
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull) | ||
.Build() | ||
|
||
let person = sut.Serialize(jackTheDriver) | ||
person |> should equal yaml | ||
|
||
type TestOmit = { | ||
name: string | ||
plop: int option | ||
} |
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,25 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFrameworks>net8.0;net7.0;net6.0;net47</TargetFrameworks> | ||
<IsPackable>false</IsPackable> | ||
<AssemblyOriginatorKeyFile>..\YamlDotNet.snk</AssemblyOriginatorKeyFile> | ||
<SignAssembly>true</SignAssembly> | ||
<LangVersion>8.0</LangVersion> | ||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="DeserializerTests.fs" /> | ||
<Compile Include="SerializerTests.fs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="coverlet.collector" Version="6.0.0" /> | ||
<PackageReference Include="FsUnit.xUnit" Version="6.0.0" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" /> | ||
<PackageReference Include="xunit" Version="2.5.3" /> | ||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="..\YamlDotNet\YamlDotNet.csproj" /> | ||
<ProjectReference Include="..\YamlDotNet.Analyzers.StaticGenerator\YamlDotNet.Analyzers.StaticGenerator.csproj" /> | ||
</ItemGroup> | ||
</Project> |
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,38 @@ | ||
using System; | ||
using YamlDotNet.Serialization; | ||
|
||
namespace YamlDotNet.Helpers | ||
{ | ||
public static class FsharpHelper | ||
{ | ||
private static bool IsFsharp(Type t) | ||
{ | ||
return t.Namespace == "Microsoft.FSharp.Core"; | ||
} | ||
|
||
public static bool IsOptionType(Type t) | ||
{ | ||
return IsFsharp(t) && t.Name == "FSharpOption`1"; | ||
} | ||
|
||
public static Type? GetOptionUnderlyingType(Type t) | ||
{ | ||
return t.IsGenericType && IsOptionType(t) ? t.GenericTypeArguments[0] : null; | ||
} | ||
|
||
public static object? GetValue(IObjectDescriptor objectDescriptor) | ||
{ | ||
if (!IsOptionType(objectDescriptor.Type)) | ||
{ | ||
throw new InvalidOperationException("Should not be called on non-Option<> type"); | ||
} | ||
|
||
if (objectDescriptor.Value is null) | ||
{ | ||
return null; | ||
} | ||
|
||
return objectDescriptor.Type.GetProperty("Value").GetValue(objectDescriptor.Value); | ||
} | ||
} | ||
} |
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
Oops, something went wrong.