Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 77bfed8

Browse files
committed
Change DeserializeBuiltin to use TypeCodes
1 parent 41649a0 commit 77bfed8

File tree

3 files changed

+140
-112
lines changed

3 files changed

+140
-112
lines changed

src/ServiceStack.Text/Common/DeserializeBuiltin.cs

Lines changed: 85 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -30,88 +30,96 @@ public static ParseStringDelegate Parse
3030

3131
private static ParseStringDelegate GetParseFn()
3232
{
33-
//Note the generic typeof(T) is faster than using var type = typeof(T)
34-
if (typeof(T) == typeof(bool))
35-
return value => value.Length == 1 ? value == "1" : bool.Parse(value);
36-
if (typeof(T) == typeof(byte))
37-
return value => byte.Parse(value, CultureInfo.InvariantCulture);
38-
if (typeof(T) == typeof(sbyte))
39-
return value => sbyte.Parse(value, CultureInfo.InvariantCulture);
40-
if (typeof(T) == typeof(short))
41-
return value => short.Parse(value, CultureInfo.InvariantCulture);
42-
if (typeof(T) == typeof(int))
43-
return value => int.Parse(value, CultureInfo.InvariantCulture);
44-
if (typeof(T) == typeof(long))
45-
return value => long.Parse(value, CultureInfo.InvariantCulture);
46-
if (typeof(T) == typeof(float))
47-
return value => float.Parse(value, CultureInfo.InvariantCulture);
48-
if (typeof(T) == typeof(double))
49-
return value => double.Parse(value, CultureInfo.InvariantCulture);
50-
if (typeof(T) == typeof(decimal))
51-
return value => decimal.Parse(value, CultureInfo.InvariantCulture);
33+
var nullableType = Nullable.GetUnderlyingType(typeof(T));
34+
if (nullableType == null)
35+
{
36+
var typeCode = Type.GetTypeCode(typeof(T));
37+
switch (typeCode)
38+
{
39+
case TypeCode.Boolean:
40+
return value => value.Length == 1 ? value == "1" : bool.Parse(value);
41+
case TypeCode.Byte:
42+
return value => byte.Parse(value, CultureInfo.InvariantCulture);
43+
case TypeCode.SByte:
44+
return value => sbyte.Parse(value, CultureInfo.InvariantCulture);
45+
case TypeCode.Int16:
46+
return value => short.Parse(value, CultureInfo.InvariantCulture);
47+
case TypeCode.UInt16:
48+
return value => ushort.Parse(value);
49+
case TypeCode.Int32:
50+
return value => int.Parse(value, CultureInfo.InvariantCulture);
51+
case TypeCode.UInt32:
52+
return value => uint.Parse(value);
53+
case TypeCode.Int64:
54+
return value => long.Parse(value, CultureInfo.InvariantCulture);
55+
case TypeCode.UInt64:
56+
return value => ulong.Parse(value);
57+
case TypeCode.Single:
58+
return value => float.Parse(value, CultureInfo.InvariantCulture);
59+
case TypeCode.Double:
60+
return value => double.Parse(value, CultureInfo.InvariantCulture);
61+
case TypeCode.Decimal:
62+
return value => decimal.Parse(value, CultureInfo.InvariantCulture);
63+
case TypeCode.Char:
64+
char cValue;
65+
return value => char.TryParse(value, out cValue) ? cValue : '\0';
66+
}
5267

53-
if (typeof(T) == typeof(Guid))
54-
return value => new Guid(value);
55-
if (typeof(T) == typeof(DateTime?))
56-
return value => DateTimeSerializer.ParseShortestNullableXsdDateTime(value);
57-
if (typeof(T) == typeof(DateTime) || typeof(T) == typeof(DateTime?))
58-
return value => DateTimeSerializer.ParseShortestXsdDateTime(value);
59-
if (typeof(T) == typeof(DateTimeOffset) || typeof(T) == typeof(DateTimeOffset?))
60-
return value => DateTimeSerializer.ParseDateTimeOffset(value);
61-
if (typeof(T) == typeof(TimeSpan))
62-
return value => DateTimeSerializer.ParseTimeSpan(value);
63-
if (typeof(T) == typeof(TimeSpan?))
64-
return value => DateTimeSerializer.ParseNullableTimeSpan(value);
68+
if (typeof(T) == typeof(Guid))
69+
return value => new Guid(value);
70+
if (typeof(T) == typeof(DateTime))
71+
return value => DateTimeSerializer.ParseShortestXsdDateTime(value);
72+
if (typeof(T) == typeof(DateTimeOffset))
73+
return value => DateTimeSerializer.ParseDateTimeOffset(value);
74+
if (typeof(T) == typeof(TimeSpan))
75+
return value => DateTimeSerializer.ParseTimeSpan(value);
6576
#if !MONOTOUCH && !SILVERLIGHT && !XBOX && !ANDROID
66-
if (typeof(T) == typeof(System.Data.Linq.Binary))
67-
return value => new System.Data.Linq.Binary(Convert.FromBase64String(value));
77+
if (typeof(T) == typeof(System.Data.Linq.Binary))
78+
return value => new System.Data.Linq.Binary(Convert.FromBase64String(value));
6879
#endif
69-
if (typeof(T) == typeof(char))
70-
{
71-
char cValue;
72-
return value => char.TryParse(value, out cValue) ? cValue : '\0';
7380
}
74-
if (typeof(T) == typeof(ushort))
75-
return value => ushort.Parse(value);
76-
if (typeof(T) == typeof(uint))
77-
return value => uint.Parse(value);
78-
if (typeof(T) == typeof(ulong))
79-
return value => ulong.Parse(value);
80-
81-
if (typeof(T) == typeof(bool?))
82-
return value => string.IsNullOrEmpty(value) ? (bool?)null : value.Length == 1 ? value == "1" : bool.Parse(value);
83-
if (typeof(T) == typeof(byte?))
84-
return value => string.IsNullOrEmpty(value) ? (byte?)null : byte.Parse(value);
85-
if (typeof(T) == typeof(sbyte?))
86-
return value => string.IsNullOrEmpty(value) ? (sbyte?)null : sbyte.Parse(value);
87-
if (typeof(T) == typeof(short?))
88-
return value => string.IsNullOrEmpty(value) ? (short?)null : short.Parse(value);
89-
if (typeof(T) == typeof(int?))
90-
return value => string.IsNullOrEmpty(value) ? (int?)null : int.Parse(value);
91-
if (typeof(T) == typeof(long?))
92-
return value => string.IsNullOrEmpty(value) ? (long?)null : long.Parse(value);
93-
if (typeof(T) == typeof(float?))
94-
return value => string.IsNullOrEmpty(value) ? (float?)null : float.Parse(value, CultureInfo.InvariantCulture);
95-
if (typeof(T) == typeof(double?))
96-
return value => string.IsNullOrEmpty(value) ? (double?)null : double.Parse(value, CultureInfo.InvariantCulture);
97-
if (typeof(T) == typeof(decimal?))
98-
return value => string.IsNullOrEmpty(value) ? (decimal?)null : decimal.Parse(value, CultureInfo.InvariantCulture);
99-
100-
if (typeof(T) == typeof(TimeSpan?))
101-
return value => string.IsNullOrEmpty(value) ? (TimeSpan?)null : TimeSpan.Parse(value);
102-
if (typeof(T) == typeof(Guid?))
103-
return value => string.IsNullOrEmpty(value) ? (Guid?)null : new Guid(value);
104-
if (typeof(T) == typeof(ushort?))
105-
return value => string.IsNullOrEmpty(value) ? (ushort?)null : ushort.Parse(value);
106-
if (typeof(T) == typeof(uint?))
107-
return value => string.IsNullOrEmpty(value) ? (uint?)null : uint.Parse(value);
108-
if (typeof(T) == typeof(ulong?))
109-
return value => string.IsNullOrEmpty(value) ? (ulong?)null : ulong.Parse(value);
110-
111-
if (typeof(T) == typeof(char?))
81+
else
11282
{
113-
char cValue;
114-
return value => string.IsNullOrEmpty(value) ? (char?)null : char.TryParse(value, out cValue) ? cValue : '\0';
83+
var typeCode = Type.GetTypeCode(nullableType);
84+
switch (typeCode)
85+
{
86+
case TypeCode.Boolean:
87+
return value => string.IsNullOrEmpty(value) ? (bool?)null : value.Length == 1 ? value == "1" : bool.Parse(value);
88+
case TypeCode.Byte:
89+
return value => string.IsNullOrEmpty(value) ? (byte?)null : byte.Parse(value);
90+
case TypeCode.SByte:
91+
return value => string.IsNullOrEmpty(value) ? (sbyte?)null : sbyte.Parse(value);
92+
case TypeCode.Int16:
93+
return value => string.IsNullOrEmpty(value) ? (short?)null : short.Parse(value);
94+
case TypeCode.UInt16:
95+
return value => string.IsNullOrEmpty(value) ? (ushort?)null : ushort.Parse(value);
96+
case TypeCode.Int32:
97+
return value => string.IsNullOrEmpty(value) ? (int?)null : int.Parse(value);
98+
case TypeCode.UInt32:
99+
return value => string.IsNullOrEmpty(value) ? (uint?)null : uint.Parse(value);
100+
case TypeCode.Int64:
101+
return value => string.IsNullOrEmpty(value) ? (long?)null : long.Parse(value);
102+
case TypeCode.UInt64:
103+
return value => string.IsNullOrEmpty(value) ? (ulong?)null : ulong.Parse(value);
104+
case TypeCode.Single:
105+
return value => string.IsNullOrEmpty(value) ? (float?)null : float.Parse(value, CultureInfo.InvariantCulture);
106+
case TypeCode.Double:
107+
return value => string.IsNullOrEmpty(value) ? (double?)null : double.Parse(value, CultureInfo.InvariantCulture);
108+
case TypeCode.Decimal:
109+
return value => string.IsNullOrEmpty(value) ? (decimal?)null : decimal.Parse(value, CultureInfo.InvariantCulture);
110+
case TypeCode.Char:
111+
char cValue;
112+
return value => string.IsNullOrEmpty(value) ? (char?)null : char.TryParse(value, out cValue) ? cValue : '\0';
113+
}
114+
115+
if (typeof(T) == typeof(DateTime?))
116+
return value => DateTimeSerializer.ParseShortestNullableXsdDateTime(value);
117+
if (typeof(T) == typeof(TimeSpan?))
118+
return value => DateTimeSerializer.ParseNullableTimeSpan(value);
119+
if (typeof(T) == typeof(Guid?))
120+
return value => string.IsNullOrEmpty(value) ? (Guid?)null : new Guid(value);
121+
if (typeof(T) == typeof(DateTimeOffset?))
122+
return value => DateTimeSerializer.ParseDateTimeOffset(value);
115123
}
116124

117125
return null;

src/ServiceStack.Text/ReflectionExtensions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ public static bool AllHaveInterfacesOfType(
139139
return true;
140140
}
141141

142+
public static TypeCode GetUnderlyingTypeCode(this Type type)
143+
{
144+
return Type.GetTypeCode(Nullable.GetUnderlyingType(type) ?? type);
145+
}
146+
142147
public static bool IsNumericType(this Type type)
143148
{
144149
if (type == null) return false;

tests/ServiceStack.Text.Tests/BclStructTests.cs

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,41 @@
66

77
namespace ServiceStack.Text.Tests
88
{
9-
public class BclStructTests : TestBase
10-
{
11-
static BclStructTests()
12-
{
13-
JsConfig<Color>.SerializeFn = c => c.ToString().Replace("Color ", "").Replace("[", "").Replace("]", "");
14-
JsConfig<Color>.DeSerializeFn = Color.FromName;
15-
}
16-
17-
[Test]
18-
public void Can_serialize_Color()
19-
{
20-
var color = Color.Red;
21-
22-
var fromColor = Serialize(color);
23-
24-
Assert.That(fromColor, Is.EqualTo(color));
25-
}
26-
27-
public enum MyEnum
28-
{
29-
Enum1,
30-
Enum2,
31-
Enum3,
32-
}
33-
34-
[Test]
35-
public void Can_serialize_arrays_of_enums()
36-
{
37-
var enums = new[] { MyEnum.Enum1, MyEnum.Enum2, MyEnum.Enum3 };
38-
var fromEnums = Serialize(enums);
39-
40-
Assert.That(fromEnums[0], Is.EqualTo(MyEnum.Enum1));
41-
Assert.That(fromEnums[1], Is.EqualTo(MyEnum.Enum2));
42-
Assert.That(fromEnums[2], Is.EqualTo(MyEnum.Enum3));
43-
}
9+
public class BclStructTests : TestBase
10+
{
11+
static BclStructTests()
12+
{
13+
JsConfig<Color>.SerializeFn = c => c.ToString().Replace("Color ", "").Replace("[", "").Replace("]", "");
14+
JsConfig<Color>.DeSerializeFn = Color.FromName;
15+
}
16+
17+
[Test]
18+
public void Can_serialize_Color()
19+
{
20+
var color = Color.Red;
21+
22+
var fromColor = Serialize(color);
23+
24+
Assert.That(fromColor, Is.EqualTo(color));
25+
}
26+
27+
public enum MyEnum
28+
{
29+
Enum1,
30+
Enum2,
31+
Enum3,
32+
}
33+
34+
[Test]
35+
public void Can_serialize_arrays_of_enums()
36+
{
37+
var enums = new[] { MyEnum.Enum1, MyEnum.Enum2, MyEnum.Enum3 };
38+
var fromEnums = Serialize(enums);
39+
40+
Assert.That(fromEnums[0], Is.EqualTo(MyEnum.Enum1));
41+
Assert.That(fromEnums[1], Is.EqualTo(MyEnum.Enum2));
42+
Assert.That(fromEnums[2], Is.EqualTo(MyEnum.Enum3));
43+
}
4444

4545
[Flags]
4646
public enum ExampleEnum
@@ -100,5 +100,20 @@ public void Can_customize_bool_deserialization()
100100
var dtoFalse = "{\"favorite\":false}".FromJson<Item>();
101101
Assert.That(dtoFalse.IsFavorite, Is.False);
102102
}
103+
104+
[Test]
105+
public void GetUnderlyingTypeCode_tests()
106+
{
107+
Assert.That(Type.GetTypeCode(typeof(int)), Is.EqualTo(TypeCode.Int32));
108+
Assert.That(Type.GetTypeCode(typeof(int?)), Is.EqualTo(TypeCode.Object));
109+
Assert.That(Type.GetTypeCode(typeof(string)), Is.EqualTo(TypeCode.String));
110+
Assert.That(Type.GetTypeCode(typeof(TypeCode)), Is.EqualTo(TypeCode.Int32)); //enum
111+
112+
Assert.That(typeof(int).GetUnderlyingTypeCode(), Is.EqualTo(TypeCode.Int32));
113+
Assert.That(typeof(int?).GetUnderlyingTypeCode(), Is.EqualTo(TypeCode.Int32));
114+
Assert.That(typeof(float?).GetUnderlyingTypeCode(), Is.EqualTo(TypeCode.Single));
115+
Assert.That(typeof(double?).GetUnderlyingTypeCode(), Is.EqualTo(TypeCode.Double));
116+
Assert.That(typeof(decimal?).GetUnderlyingTypeCode(), Is.EqualTo(TypeCode.Decimal));
117+
}
103118
}
104119
}

0 commit comments

Comments
 (0)