Skip to content

Commit

Permalink
Merge pull request #55 from oskardudycz/master
Browse files Browse the repository at this point in the history
Fix Money type deserialization
  • Loading branch information
Rémy van Duijkeren authored Nov 18, 2017
2 parents a6a6f34 + 270c721 commit 6cee961
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 5 deletions.
13 changes: 10 additions & 3 deletions src/NodaMoney.Serialization.AspNet/MoneyJavaScriptConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@ public override object Deserialize(IDictionary<string, object> dictionary, Type
if (type != typeof(Money))
throw new ArgumentException("object should be of type Money to deserialize!", nameof(type));

decimal amount = decimal.Parse((string)dictionary["amount"], CultureInfo.InvariantCulture);
string code = (string)dictionary["currency"];
if (!dictionary.ContainsKey("amount"))
throw new ArgumentNullException("Ammount needs to be defined", "amount");

if (!dictionary.ContainsKey("currency"))
throw new ArgumentNullException("Currency needs to be defined", "currency");

var amount = decimal.Parse(Convert.ToString(dictionary["amount"], CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);

var code = (string)dictionary["currency"];

return new Money(amount, Currency.FromCode(code));
}
Expand All @@ -42,7 +49,7 @@ public override object Deserialize(IDictionary<string, object> dictionary, Type
/// <param name="serializer">The object that is responsible for the serialization.</param>
/// <returns>An object that contains key/value pairs that represent the object’s data.</returns>
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
{
Money money = (Money)obj;

var dictionary = new Dictionary<string, object>
Expand Down
12 changes: 11 additions & 1 deletion src/NodaMoney/Serialization/JsonNet/MoneyJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,17 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist

JObject jsonObject = JObject.Load(reader);
var properties = jsonObject.Properties().ToList();
return new Money((decimal)properties[0].Value, Currency.FromCode((string)properties[1].Value));

var amountProperty = properties.SingleOrDefault(pr => string.Compare(pr.Name, "amount", StringComparison.OrdinalIgnoreCase) == 0);
var currencyProperty = properties.SingleOrDefault(pr => string.Compare(pr.Name, "currency", StringComparison.OrdinalIgnoreCase) == 0);

if (amountProperty == null)
throw new ArgumentNullException("Ammount needs to be defined", "amount");

if (currencyProperty == null)
throw new ArgumentNullException("Currency needs to be defined", "currency");

return new Money((decimal)amountProperty.Value, Currency.FromCode((string)currencyProperty.Value));
}

/// <summary>Determines whether this instance can convert the specified object type.</summary>
Expand Down
136 changes: 135 additions & 1 deletion tests/NodaMoney.Serialization.AspNet.Tests/MoneySerializableTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Web.Script.Serialization;
using FluentAssertions;
using Newtonsoft.Json;
using NodaMoney.Serialization.JsonNet;
using Xunit;

namespace NodaMoney.Serialization.AspNet.Tests
Expand Down Expand Up @@ -30,5 +33,136 @@ public void WhenSerializing_ThenThisShouldSucceed(Money money)
clone.Should().Be(money);
}
}

public class GivenIWantToSerializeMoneyWithJavaScriptConverter
{
public static IEnumerable<object[]> TestData => new[]
{
new object[] { new Money(765m, Currency.FromCode("JPY")) },
new object[] { new Money(765.43m, Currency.FromCode("EUR")) }
};

[Theory]
[MemberData("TestData")]
public void WhenSerializing_ThenThisShouldSucceed(Money money)
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new MoneyJsonConverter() }
};

var json = JsonConvert.SerializeObject(money);
// Console.WriteLine(json);
var clone = JsonConvert.DeserializeObject<Money>(json);

clone.Should().Be(money);
}
}

public class GivenIWantToDeserializeMoneyWithJavaScriptSerializer
{
private static string CurrentCultureCode = new RegionInfo(CultureInfo.CurrentCulture.LCID).ISOCurrencySymbol;

public static IEnumerable<object[]> ValidJsonData => new[]
{
new object[] { $"{{ amount: '200', currency: '{CurrentCultureCode}' }}", },
new object[] { $"{{ amount: 200, currency: '{CurrentCultureCode}' }}" },
new object[] { $"{{ currency: '{CurrentCultureCode}', amount: 200 }}" },
new object[] { $"{{ currency: '{CurrentCultureCode}', amount: '200' }}" }
};

public static IEnumerable<object[]> InvalidJsonData => new[]
{
new object[] { "{ amount: '200' }" },
new object[] { "{ amount: 200 }" },
new object[] { $"{{ currency: '{CurrentCultureCode}' }}" },
};

[Theory]
[MemberData("ValidJsonData")]
public void WhenDeserializingWithValidJSON_ThenThisShouldSucceed(string json)
{
var money = new Money(200, Currency.FromCode(CurrentCultureCode));

var jsSerializer = new JavaScriptSerializer();
jsSerializer.RegisterConverters(new JavaScriptConverter[] { new MoneyJavaScriptConverter() });

// Console.WriteLine(json);
var clone = jsSerializer.Deserialize<Money>(json);

clone.Should().Be(money);
}

[Theory]
[MemberData("InvalidJsonData")]
public void WhenDeserializingWithInvalidJSON_ThenThisShouldFail(string json)
{
var money = new Money(200, Currency.FromCode(CurrentCultureCode));

var jsSerializer = new JavaScriptSerializer();
jsSerializer.RegisterConverters(new JavaScriptConverter[] { new MoneyJavaScriptConverter() });

var exception = Record.Exception(() =>
jsSerializer.Deserialize<Money>(json)
);

exception.Should().BeOfType<ArgumentNullException>();
}
}

public class GivenIWantToDeserializeMoneyWithJavaScriptConverter
{
private static string CurrentCultureCode = new RegionInfo(CultureInfo.CurrentCulture.LCID).ISOCurrencySymbol;

public static IEnumerable<object[]> ValidJsonData => new[]
{
new object[] { $"{{ amount: '200', currency: '{CurrentCultureCode}' }}", },
new object[] { $"{{ amount: 200, currency: '{CurrentCultureCode}' }}" },
new object[] { $"{{ currency: '{CurrentCultureCode}', amount: 200 }}" },
new object[] { $"{{ currency: '{CurrentCultureCode}', amount: '200' }}" }
};

public static IEnumerable<object[]> InvalidJsonData => new[]
{
new object[] { "{ amount: '200' }" },
new object[] { "{ amount: 200 }" },
new object[] { $"{{ currency: '{CurrentCultureCode}' }}" },
};

[Theory]
[MemberData("ValidJsonData")]
public void WhenDeserializingWithInvalidJSON_ThenThisShouldFail(string json)
{
var money = new Money(200, Currency.FromCode(CurrentCultureCode));

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new MoneyJsonConverter() }
};

// Console.WriteLine(json);
var clone = JsonConvert.DeserializeObject<Money>(json);

clone.Should().Be(money);
}

[Theory]
[MemberData("InvalidJsonData")]
public void WhenDeserializing_ThenThisShouldSucceed(string json)
{
var money = new Money(200, Currency.FromCode(CurrentCultureCode));

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = new List<JsonConverter> { new MoneyJsonConverter() }
};

var exception = Record.Exception(() =>
JsonConvert.DeserializeObject<Money>(json)
);

exception.Should().BeOfType<ArgumentNullException>();
}
}
}
}
}

0 comments on commit 6cee961

Please sign in to comment.