Skip to content
This repository was archived by the owner on Jun 17, 2025. It is now read-only.

Commit f0324f5

Browse files
committed
Merge pull request JSONAPIdotNET#97 from cybermats/payload2
Adding globalization for decimal, double and single for conversion.
2 parents 74fd025 + 9e185df commit f0324f5

4 files changed

Lines changed: 79 additions & 8 deletions

File tree

JSONAPI.Tests/ActionFilters/DefaultFilteringTransformerTests.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Linq;
45
using System.Net;
56
using System.Net.Http;
7+
using System.Threading;
68
using System.Web.Http;
79
using FluentAssertions;
810
using JSONAPI.ActionFilters;
@@ -689,6 +691,19 @@ public void Filters_by_matching_decimal_property()
689691
returnedArray[0].Id.Should().Be("170");
690692
}
691693

694+
[TestMethod]
695+
public void Filters_by_matching_decimal_property_non_en_US()
696+
{
697+
var currentCulture = Thread.CurrentThread.CurrentCulture;
698+
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
699+
700+
var returnedArray = GetArray("http://api.example.com/dummies?filter[decimal-field]=4.03");
701+
returnedArray.Length.Should().Be(1);
702+
returnedArray[0].Id.Should().Be("170");
703+
704+
Thread.CurrentThread.CurrentCulture = currentCulture;
705+
}
706+
692707
[TestMethod]
693708
public void Filters_by_missing_decimal_property()
694709
{
@@ -1039,6 +1054,20 @@ public void Filters_by_matching_single_property()
10391054
returnedArray[0].Id.Should().Be("370");
10401055
}
10411056

1057+
[TestMethod]
1058+
public void Filters_by_matching_single_property_non_en_US()
1059+
{
1060+
var currentCulture = Thread.CurrentThread.CurrentCulture;
1061+
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
1062+
1063+
var returnedArray = GetArray("http://api.example.com/dummies?filter[single-field]=21.56901");
1064+
returnedArray.Length.Should().Be(1);
1065+
returnedArray[0].Id.Should().Be("370");
1066+
1067+
Thread.CurrentThread.CurrentCulture = currentCulture;
1068+
}
1069+
1070+
10421071
[TestMethod]
10431072
public void Filters_by_missing_single_property()
10441073
{
@@ -1074,6 +1103,19 @@ public void Filters_by_matching_double_property()
10741103
returnedArray[0].Id.Should().Be("390");
10751104
}
10761105

1106+
[TestMethod]
1107+
public void Filters_by_matching_double_property_non_en_US()
1108+
{
1109+
var currentCulture = Thread.CurrentThread.CurrentCulture;
1110+
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
1111+
1112+
var returnedArray = GetArray("http://api.example.com/dummies?filter[double-field]=12.3453489012");
1113+
returnedArray.Length.Should().Be(1);
1114+
returnedArray[0].Id.Should().Be("390");
1115+
1116+
Thread.CurrentThread.CurrentCulture = currentCulture;
1117+
}
1118+
10771119
[TestMethod]
10781120
public void Filters_by_missing_double_property()
10791121
{

JSONAPI.Tests/Core/ResourceTypeRegistrarTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
using System.Collections.Generic;
88
using System.Collections;
99
using System.Diagnostics;
10+
using System.Globalization;
1011
using System.Linq;
12+
using System.Threading;
1113
using FluentAssertions;
1214
using Newtonsoft.Json;
1315
using Newtonsoft.Json.Linq;
@@ -561,6 +563,24 @@ public void BuildRegistration_sets_up_correct_attribute_for_Decimal_field()
561563
AssertAttribute(reg, "decimal-field", null, 0m, "0", g => g.DecimalField);
562564
}
563565

566+
[TestMethod]
567+
public void BuildRegistration_sets_up_correct_attribute_for_Decimal_field_non_en_US()
568+
{
569+
// Set up non US culture
570+
var culture = Thread.CurrentThread.CurrentCulture;
571+
Thread.CurrentThread.CurrentCulture = new CultureInfo("se-SE");
572+
573+
// Arrange
574+
var registrar = new ResourceTypeRegistrar(new DefaultNamingConventions(new PluralizationService()));
575+
576+
// Act
577+
var reg = registrar.BuildRegistration(typeof(AttributeGrabBag));
578+
579+
AssertAttribute(reg, "decimal-field", "20000000000.1234", 20000000000.1234m, "20000000000.1234", g => g.DecimalField);
580+
581+
Thread.CurrentThread.CurrentCulture = culture;
582+
}
583+
564584
[TestMethod]
565585
public void BuildRegistration_sets_up_correct_attribute_for_nullable_Decimal_field()
566586
{

JSONAPI/Core/DecimalAttributeValueConverter.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using System.Reflection;
34
using Newtonsoft.Json;
45
using Newtonsoft.Json.Linq;
@@ -26,7 +27,14 @@ public JToken GetValue(object resource)
2627
{
2728
var value = _property.GetValue(resource);
2829
if (value == null) return null;
29-
return value.ToString();
30+
try
31+
{
32+
return ((Decimal)value).ToString(CultureInfo.InvariantCulture);
33+
}
34+
catch (InvalidCastException e)
35+
{
36+
throw new JsonSerializationException("Could not serialize decimal value.", e);
37+
}
3038
}
3139

3240
public void SetValue(object resource, JToken value)
@@ -37,7 +45,7 @@ public void SetValue(object resource, JToken value)
3745
{
3846
var stringTokenValue = value.Value<string>();
3947
Decimal d;
40-
if (!Decimal.TryParse(stringTokenValue, out d))
48+
if (!Decimal.TryParse(stringTokenValue, NumberStyles.Any, CultureInfo.InvariantCulture, out d))
4149
throw new JsonSerializationException("Could not parse decimal value.");
4250
_property.SetValue(resource, d);
4351
}

JSONAPI/QueryableTransformers/DefaultFilteringTransformer.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Globalization;
23
using System.Linq;
34
using System.Linq.Expressions;
45
using System.Net;
@@ -248,40 +249,40 @@ private Expression GetPredicateBodyForField(ResourceTypeAttribute resourceTypeAt
248249
else if (propertyType == typeof(Single))
249250
{
250251
Single value;
251-
expr = Single.TryParse(queryValue, out value)
252+
expr = Single.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out value)
252253
? GetPropertyExpression(value, prop, param)
253254
: Expression.Constant(false);
254255
}
255256
else if (propertyType == typeof(Single?))
256257
{
257258
Single tmp;
258-
var value = Single.TryParse(queryValue, out tmp) ? tmp : (Single?)null;
259+
var value = Single.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out tmp) ? tmp : (Single?)null;
259260
expr = GetPropertyExpression(value, prop, param);
260261
}
261262
else if (propertyType == typeof(Double))
262263
{
263264
Double value;
264-
expr = Double.TryParse(queryValue, out value)
265+
expr = Double.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out value)
265266
? GetPropertyExpression(value, prop, param)
266267
: Expression.Constant(false);
267268
}
268269
else if (propertyType == typeof(Double?))
269270
{
270271
Double tmp;
271-
var value = Double.TryParse(queryValue, out tmp) ? tmp : (Double?)null;
272+
var value = Double.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out tmp) ? tmp : (Double?)null;
272273
expr = GetPropertyExpression(value, prop, param);
273274
}
274275
else if (propertyType == typeof(Decimal))
275276
{
276277
Decimal value;
277-
expr = Decimal.TryParse(queryValue, out value)
278+
expr = Decimal.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out value)
278279
? GetPropertyExpression(value, prop, param)
279280
: Expression.Constant(false);
280281
}
281282
else if (propertyType == typeof(Decimal?))
282283
{
283284
Decimal tmp;
284-
var value = Decimal.TryParse(queryValue, out tmp) ? tmp : (Decimal?)null;
285+
var value = Decimal.TryParse(queryValue, NumberStyles.Any, CultureInfo.InvariantCulture, out tmp) ? tmp : (Decimal?)null;
285286
expr = GetPropertyExpression(value, prop, param);
286287
}
287288
else if (propertyType == typeof(DateTime))

0 commit comments

Comments
 (0)