Skip to content

Commit 9e2e21c

Browse files
committed
standardize on InvariantCulture but make it overridable in Deserializers via Culture property
1 parent 0558520 commit 9e2e21c

File tree

6 files changed

+84
-61
lines changed

6 files changed

+84
-61
lines changed

RestSharp.Tests/JsonTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ public void Can_Deserialize_Custom_Formatted_Date()
115115

116116
var formatted = new
117117
{
118-
StartDate = date.ToString(format, CultureInfo.InvariantCulture)
118+
StartDate = date.ToString(format)
119119
};
120120

121121
var data = JsonConvert.SerializeObject(formatted);

RestSharp/Deserializers/JsonDeserializer.cs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public class JsonDeserializer : IDeserializer
3030
public string RootElement { get; set; }
3131
public string Namespace { get; set; }
3232
public string DateFormat { get; set; }
33+
public CultureInfo Culture { get; set; }
34+
35+
public JsonDeserializer()
36+
{
37+
Culture = CultureInfo.InvariantCulture;
38+
}
3339

3440
public T Deserialize<T>(RestResponse response) where T : new()
3541
{
@@ -91,7 +97,7 @@ private void Map(object x, JToken json)
9197
if (value == null)
9298
{
9399
// try camel cased name
94-
actualName = name.ToCamelCase();
100+
actualName = name.ToCamelCase(Culture);
95101
value = json[actualName];
96102
}
97103

@@ -171,19 +177,19 @@ private void Map(object x, JToken json)
171177
if (DateFormat.HasValue())
172178
{
173179
var clean = value.ToString().RemoveSurroundingQuotes();
174-
dt = DateTime.ParseExact(clean, DateFormat, CultureInfo.InvariantCulture);
180+
dt = DateTime.ParseExact(clean, DateFormat, Culture);
175181
}
176182
else
177183
{
178184
// try parsing instead
179-
dt = value.ToString().ParseJsonDate();
185+
dt = value.ToString().ParseJsonDate(Culture);
180186
}
181187

182188
prop.SetValue(x, dt, null);
183189
}
184190
else if (type == typeof(Decimal))
185191
{
186-
var dec = Decimal.Parse(value.ToString());
192+
var dec = Decimal.Parse(value.ToString(), Culture);
187193
prop.SetValue(x, dec, null);
188194
}
189195
else if (type == typeof(Guid))

RestSharp/Deserializers/XmlAttributeDeserializer.cs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public class XmlAttributeDeserializer : IDeserializer
2929
public string RootElement { get; set; }
3030
public string Namespace { get; set; }
3131
public string DateFormat { get; set; }
32+
public CultureInfo Culture { get; set; }
33+
34+
public XmlAttributeDeserializer()
35+
{
36+
Culture = CultureInfo.InvariantCulture;
37+
}
3238

3339
public T Deserialize<T>(RestResponse response) where T : new()
3440
{
@@ -104,35 +110,35 @@ private void Map(object x, XElement root)
104110

105111
if (value == null)
106112
{
107-
// special case for inline list items
108-
if (type.IsGenericType)
109-
{
110-
var genericType = type.GetGenericArguments()[0];
111-
112-
var first = GetElementByName(root, genericType.Name);
113-
if (first != null)
114-
{
115-
var elements = root.Elements(first.Name);
116-
117-
var list = (IList)Activator.CreateInstance(type);
118-
PopulateListFromElements(genericType, elements, list);
119-
prop.SetValue(x, list, null);
120-
121-
}
122-
}
123-
continue;
113+
// special case for inline list items
114+
if (type.IsGenericType)
115+
{
116+
var genericType = type.GetGenericArguments()[0];
117+
118+
var first = GetElementByName(root, genericType.Name);
119+
if (first != null)
120+
{
121+
var elements = root.Elements(first.Name);
122+
123+
var list = (IList)Activator.CreateInstance(type);
124+
PopulateListFromElements(genericType, elements, list);
125+
prop.SetValue(x, list, null);
126+
127+
}
128+
}
129+
continue;
124130
}
125131

126-
// check for nullable and extract underlying type
127-
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
128-
{
129-
type = type.GetGenericArguments()[0];
132+
// check for nullable and extract underlying type
133+
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
134+
{
135+
type = type.GetGenericArguments()[0];
130136

131-
if (string.IsNullOrEmpty(value.ToString()))
132-
{
133-
continue;
134-
}
135-
}
137+
if (string.IsNullOrEmpty(value.ToString()))
138+
{
139+
continue;
140+
}
141+
}
136142

137143
if (type.IsPrimitive)
138144
{
@@ -156,7 +162,7 @@ private void Map(object x, XElement root)
156162
{
157163
if (DateFormat.HasValue())
158164
{
159-
value = DateTime.ParseExact(value.ToString(), DateFormat, CultureInfo.CurrentCulture);
165+
value = DateTime.ParseExact(value.ToString(), DateFormat, Culture);
160166
}
161167
else
162168
{
@@ -233,7 +239,7 @@ private object HandleListDerivative(object x, XElement root, string propName, Ty
233239
}
234240

235241
var lowerName = name.ToLower();
236-
var camelName = name.ToCamelCase();
242+
var camelName = name.ToCamelCase(Culture);
237243

238244
var list = (IList)Activator.CreateInstance(type);
239245

@@ -311,7 +317,7 @@ private object GetValueFromXml(XElement root, XName name, bool attribute)
311317
private XElement GetElementByName(XElement root, XName name)
312318
{
313319
var lowerName = XName.Get(name.LocalName.ToLower(), name.NamespaceName);
314-
var camelName = XName.Get(name.LocalName.ToCamelCase(), name.NamespaceName);
320+
var camelName = XName.Get(name.LocalName.ToCamelCase(Culture), name.NamespaceName);
315321

316322
if (root.Element(name) != null)
317323
{
@@ -346,7 +352,7 @@ private XElement GetElementByName(XElement root, XName name)
346352
private XAttribute GetAttributeByName(XElement root, XName name)
347353
{
348354
var lowerName = XName.Get(name.LocalName.ToLower(), name.NamespaceName);
349-
var camelName = XName.Get(name.LocalName.ToCamelCase(), name.NamespaceName);
355+
var camelName = XName.Get(name.LocalName.ToCamelCase(Culture), name.NamespaceName);
350356

351357
if (root.Attribute(name) != null)
352358
{

RestSharp/Deserializers/XmlDeserializer.cs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ public class XmlDeserializer : IDeserializer
3030
public string RootElement { get; set; }
3131
public string Namespace { get; set; }
3232
public string DateFormat { get; set; }
33+
public CultureInfo Culture { get; set; }
34+
35+
public XmlDeserializer()
36+
{
37+
Culture = CultureInfo.InvariantCulture;
38+
}
3339

3440
public T Deserialize<T>(RestResponse response) where T : new()
3541
{
@@ -143,18 +149,18 @@ private void Map(object x, XElement root)
143149
{
144150
if (DateFormat.HasValue())
145151
{
146-
value = DateTime.ParseExact(value.ToString(), DateFormat, CultureInfo.CurrentCulture);
152+
value = DateTime.ParseExact(value.ToString(), DateFormat, Culture);
147153
}
148154
else
149155
{
150-
value = DateTime.Parse(value.ToString());
156+
value = DateTime.Parse(value.ToString(), Culture);
151157
}
152158

153159
prop.SetValue(x, value, null);
154160
}
155161
else if (type == typeof(Decimal))
156162
{
157-
value = Decimal.Parse(value.ToString());
163+
value = Decimal.Parse(value.ToString(), Culture);
158164
prop.SetValue(x, value, null);
159165
}
160166
else if (type == typeof(Guid))
@@ -235,7 +241,7 @@ private object HandleListDerivative(object x, XElement root, string propName, Ty
235241

236242
if (!elements.Any())
237243
{
238-
var camelName = name.ToCamelCase().AsNamespaced(Namespace);
244+
var camelName = name.ToCamelCase(Culture).AsNamespaced(Namespace);
239245
elements = root.Descendants(camelName);
240246
}
241247

@@ -293,7 +299,7 @@ private object GetValueFromXml(XElement root, XName name)
293299
private XElement GetElementByName(XElement root, XName name)
294300
{
295301
var lowerName = name.LocalName.ToLower().AsNamespaced(name.NamespaceName);
296-
var camelName = name.LocalName.ToCamelCase().AsNamespaced(name.NamespaceName);
302+
var camelName = name.LocalName.ToCamelCase(Culture).AsNamespaced(name.NamespaceName);
297303

298304
if (root.Element(name) != null)
299305
{
@@ -334,7 +340,7 @@ private XElement GetElementByName(XElement root, XName name)
334340
private XAttribute GetAttributeByName(XElement root, XName name)
335341
{
336342
var lowerName = name.LocalName.ToLower().AsNamespaced(name.NamespaceName);
337-
var camelName = name.LocalName.ToCamelCase().AsNamespaced(name.NamespaceName);
343+
var camelName = name.LocalName.ToCamelCase(Culture).AsNamespaced(name.NamespaceName);
338344

339345
if (root.Attribute(name) != null)
340346
{

RestSharp/Extensions/StringExtensions.cs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public static string RemoveUnderscoresAndDashes(this string input)
9494
/// </summary>
9595
/// <param name="input">JSON value to parse</param>
9696
/// <returns>DateTime</returns>
97-
public static DateTime ParseJsonDate(this string input)
97+
public static DateTime ParseJsonDate(this string input, CultureInfo culture)
9898
{
9999
input = input.Replace("\n", "");
100100
input = input.Replace("\r", "");
@@ -103,17 +103,17 @@ public static DateTime ParseJsonDate(this string input)
103103

104104
if (input.Contains("/Date("))
105105
{
106-
return ExtractDate(input, @"\\/Date\((-?\d+)(-|\+)?([0-9]{4})?\)\\/");
106+
return ExtractDate(input, @"\\/Date\((-?\d+)(-|\+)?([0-9]{4})?\)\\/", culture);
107107
}
108108

109109
if (input.Contains("new Date("))
110110
{
111111
input = input.Replace(" ", "");
112112
// because all whitespace is removed, match against newDate( instead of new Date(
113-
return ExtractDate(input, @"newDate\((-?\d+)*\)");
113+
return ExtractDate(input, @"newDate\((-?\d+)*\)", culture);
114114
}
115115

116-
return ParseFormattedDate(input);
116+
return ParseFormattedDate(input, culture);
117117
}
118118

119119
/// <summary>
@@ -131,7 +131,7 @@ public static string RemoveSurroundingQuotes(this string input)
131131
return input;
132132
}
133133

134-
private static DateTime ParseFormattedDate(string input)
134+
private static DateTime ParseFormattedDate(string input, CultureInfo culture)
135135
{
136136
var formats = new[] {
137137
"u",
@@ -144,17 +144,15 @@ private static DateTime ParseFormattedDate(string input)
144144
};
145145

146146
DateTime date;
147-
if (DateTime.TryParseExact(input, formats,
148-
CultureInfo.InvariantCulture,
149-
DateTimeStyles.None, out date))
147+
if (DateTime.TryParseExact(input, formats, culture, DateTimeStyles.None, out date))
150148
{
151149
return date;
152150
}
153151

154152
return default(DateTime);
155153
}
156154

157-
private static DateTime ExtractDate(string input, string pattern)
155+
private static DateTime ExtractDate(string input, string pattern, CultureInfo culture)
158156
{
159157
DateTime dt = DateTime.MinValue;
160158
var regex = new Regex(pattern);
@@ -169,7 +167,7 @@ private static DateTime ExtractDate(string input, string pattern)
169167
// adjust if time zone modifier present
170168
if (match.Groups.Count > 2 && !String.IsNullOrEmpty(match.Groups[3].Value))
171169
{
172-
var mod = DateTime.ParseExact(match.Groups[3].Value, "HHmm", CultureInfo.InvariantCulture);
170+
var mod = DateTime.ParseExact(match.Groups[3].Value, "HHmm", culture);
173171
if (match.Groups[2].Value == "+")
174172
{
175173
dt = dt.Add(mod.TimeOfDay);
@@ -200,9 +198,9 @@ public static bool Matches(this string input, string pattern)
200198
/// </summary>
201199
/// <param name="lowercaseAndUnderscoredWord">String to convert</param>
202200
/// <returns>string</returns>
203-
public static string ToPascalCase(this string lowercaseAndUnderscoredWord)
201+
public static string ToPascalCase(this string lowercaseAndUnderscoredWord, CultureInfo culture)
204202
{
205-
return ToPascalCase(lowercaseAndUnderscoredWord, true);
203+
return ToPascalCase(lowercaseAndUnderscoredWord, true, culture);
206204
}
207205

208206
/// <summary>
@@ -211,7 +209,7 @@ public static string ToPascalCase(this string lowercaseAndUnderscoredWord)
211209
/// <param name="text">String to convert</param>
212210
/// <param name="removeUnderscores">Option to remove underscores</param>
213211
/// <returns></returns>
214-
public static string ToPascalCase(this string text, bool removeUnderscores)
212+
public static string ToPascalCase(this string text, bool removeUnderscores, CultureInfo culture)
215213
{
216214
if (String.IsNullOrEmpty(text))
217215
return text;
@@ -229,25 +227,25 @@ public static string ToPascalCase(this string text, bool removeUnderscores)
229227
string restOfWord = word.Substring(1);
230228

231229
if (restOfWord.IsUpperCase())
232-
restOfWord = restOfWord.ToLower(CultureInfo.CurrentUICulture);
230+
restOfWord = restOfWord.ToLower(culture);
233231

234-
char firstChar = char.ToUpper(word[0], CultureInfo.CurrentUICulture);
232+
char firstChar = char.ToUpper(word[0], culture);
235233
words[i] = String.Concat(firstChar, restOfWord);
236234
}
237235
}
238236
return String.Join(joinString, words);
239237
}
240-
return String.Concat(words[0].Substring(0, 1).ToUpper(CultureInfo.CurrentUICulture), words[0].Substring(1));
238+
return String.Concat(words[0].Substring(0, 1).ToUpper(culture), words[0].Substring(1));
241239
}
242240

243241
/// <summary>
244242
/// Converts a string to camel case
245243
/// </summary>
246244
/// <param name="lowercaseAndUnderscoredWord">String to convert</param>
247245
/// <returns>String</returns>
248-
public static string ToCamelCase(this string lowercaseAndUnderscoredWord)
246+
public static string ToCamelCase(this string lowercaseAndUnderscoredWord, CultureInfo culture)
249247
{
250-
return MakeInitialLowerCase(ToPascalCase(lowercaseAndUnderscoredWord));
248+
return MakeInitialLowerCase(ToPascalCase(lowercaseAndUnderscoredWord, culture));
251249
}
252250

253251
/// <summary>

RestSharp/Serializers/SerializeAsAttribute.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
using System;
1818
using RestSharp.Extensions;
19+
using System.Globalization;
1920

2021
namespace RestSharp.Serializers
2122
{
@@ -30,6 +31,7 @@ public sealed class SerializeAsAttribute : Attribute
3031
public SerializeAsAttribute() {
3132
NameStyle = NameStyle.AsIs;
3233
Index = int.MaxValue;
34+
Culture = CultureInfo.InvariantCulture;
3335
}
3436

3537
/// <summary>
@@ -42,6 +44,11 @@ public SerializeAsAttribute() {
4244
/// </summary>
4345
public bool Attribute { get; set; }
4446

47+
/// <summary>
48+
/// The culture to use when serializing
49+
/// </summary>
50+
public CultureInfo Culture { get; set; }
51+
4552
/// <summary>
4653
/// Transforms the casing of the name based on the selected value.
4754
/// </summary>
@@ -61,9 +68,9 @@ public string TransformName(string input) {
6168
var name = Name ?? input;
6269
switch (NameStyle) {
6370
case NameStyle.CamelCase:
64-
return name.ToCamelCase();
71+
return name.ToCamelCase(Culture);
6572
case NameStyle.PascalCase:
66-
return name.ToPascalCase();
73+
return name.ToPascalCase(Culture);
6774
case NameStyle.LowerCase:
6875
return name.ToLower();
6976
}

0 commit comments

Comments
 (0)