Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/louthy/language-ext
Browse files Browse the repository at this point in the history
  • Loading branch information
louthy committed Dec 31, 2019
2 parents 2338516 + e1179d4 commit b39366d
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 33 deletions.
14 changes: 4 additions & 10 deletions LanguageExt.CodeGen/CodeGenUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1980,7 +1980,7 @@ static MemberDeclarationSyntax[] MakeSerialisationMembers(string typeName, List<
Identifier(typeName))
.WithModifiers(
TokenList(
Token(SyntaxKind.ProtectedKeyword)))
Token(SyntaxKind.PrivateKeyword)))
.WithParameterList(
ParameterList(
SeparatedList<ParameterSyntax>(
Expand Down Expand Up @@ -2213,9 +2213,7 @@ public static TypeDeclarationSyntax MakeCaseType(
Token(SyntaxKind.CommaToken),
SimpleBaseType(thisComparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(comparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(serializableType)
SimpleBaseType(comparableType)
}))),
BaseSpec.Abstract =>
type.WithBaseList(
Expand All @@ -2228,9 +2226,7 @@ public static TypeDeclarationSyntax MakeCaseType(
Token(SyntaxKind.CommaToken),
SimpleBaseType(thisComparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(comparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(serializableType)
SimpleBaseType(comparableType)
}))),
_ =>
type.WithBaseList(
Expand All @@ -2241,9 +2237,7 @@ public static TypeDeclarationSyntax MakeCaseType(
Token(SyntaxKind.CommaToken),
SimpleBaseType(thisComparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(comparableType),
Token(SyntaxKind.CommaToken),
SimpleBaseType(serializableType)
SimpleBaseType(comparableType)
})))
};

Expand Down
107 changes: 107 additions & 0 deletions LanguageExt.Tests/UnionCustomJsonSerializerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Xunit;

namespace LanguageExt.Tests
{
public partial class UnionCustomJsonSerializerTests
{
[Union]
[MyUnion]
abstract partial class UnionTestClass
{
public abstract UnionTestClass A();
public abstract UnionTestClass B(int i);
public abstract UnionTestClass C(int i);
public abstract UnionTestClass D(int i, int j);
}

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class MyUnionAttribute : Attribute
{
}

public class UnionJsonReadConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
string typeName = null;
JObject typeValueToken = null;
if (reader.TokenType != JsonToken.StartObject) throw new Exception();
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndObject) break;
if (reader.TokenType != JsonToken.PropertyName) throw new Exception();
if ((string) reader.Value == "Type")
{
if (!reader.Read()) throw new Exception();
if (typeName != null) throw new Exception();
if (reader.TokenType != JsonToken.String) throw new Exception();
typeName = (string) reader.Value;
}
else if ((string) reader.Value == "Value")
{
if (typeValueToken != null) throw new Exception();
if (!reader.Read()) throw new Exception();
if (reader.TokenType != JsonToken.StartObject) throw new Exception();
typeValueToken = JObject.Load(reader);
}
}

var type = objectType.Assembly.GetTypes().Where(_ => objectType.IsAssignableFrom(_) && _.Name == typeName).Single();
var result = typeValueToken.ToObject(type, serializer);
return result;
}

public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType.IsClass && objectType.GetCustomAttribute<MyUnionAttribute>() != null;
}

public class UnionJsonWriteConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var t = value.GetType();
writer.WriteStartObject();
writer.WritePropertyName("Type");
writer.WriteValue(t.Name);
writer.WritePropertyName("Value");
writer.WriteStartObject();
foreach (var fieldInfo in t.GetFields(BindingFlags.Instance | BindingFlags.Public))
{
writer.WritePropertyName(fieldInfo.Name);
serializer.Serialize(writer, fieldInfo.GetValue(value));
}
writer.WriteEndObject();
writer.WriteEndObject();
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
new NotImplementedException();

public override bool CanRead => false;

public override bool CanConvert(Type objectType) => objectType.IsClass && objectType.BaseType?.BaseType?.GetCustomAttribute<MyUnionAttribute>() != null;
}

[Fact]
public void UnionFromJson()
{
var json = @"{""Type"":""B"",""Value"":{""I"":42}}";
var x = JsonConvert.DeserializeObject<UnionTestClass>(json, new UnionJsonReadConverter()) as B;
Assert.Equal(42, x?.I);
}

[Fact]
public void UnionToJson()
{
var x = JsonConvert.SerializeObject(UnionTestClassCon.B(42), new UnionJsonWriteConverter());
Assert.Equal(@"{""Type"":""B"",""Value"":{""I"":42}}", x);
}
}
}
40 changes: 40 additions & 0 deletions LanguageExt.Tests/UnionJsonSerializerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Xunit;

namespace LanguageExt.Tests
{
public partial class UnionJsonSerializerTests
{
[Union]
public abstract partial class LightControl
{
public abstract LightControl OnOff(bool enabled);
public abstract LightControl Dimmer(int value);
}

[Fact]
public void UnionInstanceFromJson()
{
var json = @"{""Value"":100}";
var x = JsonConvert.DeserializeObject<Dimmer>(json);
Assert.Equal(100, x.Value);
}

[Fact]
public void UnionInstanceToJson()
{
Assert.Equal(@"{""Value"":100}", JsonConvert.SerializeObject(LightControlCon.Dimmer(100)));
}

[Fact]
public void UnionRoundTrip()
{
Assert.Equal(LightControlCon.OnOff(true), JsonConvert.DeserializeObject<OnOff>(JsonConvert.SerializeObject(LightControlCon.OnOff(true))));
Assert.Equal(LightControlCon.OnOff(false), JsonConvert.DeserializeObject<OnOff>(JsonConvert.SerializeObject(LightControlCon.OnOff(false))));
Assert.Equal(LightControlCon.Dimmer(10), JsonConvert.DeserializeObject<Dimmer>(JsonConvert.SerializeObject(LightControlCon.Dimmer(10))));
Assert.Equal(LightControlCon.Dimmer(90), JsonConvert.DeserializeObject<Dimmer>(JsonConvert.SerializeObject(LightControlCon.Dimmer(90))));

}
}
}
23 changes: 0 additions & 23 deletions LanguageExt.Tests/UnionTests.cs

This file was deleted.

0 comments on commit b39366d

Please sign in to comment.