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

Commit 7d51fa1

Browse files
committed
Add new JsConfig.ParsePrimitiveFn to allow short-circuiting of parse primitive values
1 parent 2e07461 commit 7d51fa1

File tree

4 files changed

+72
-5
lines changed

4 files changed

+72
-5
lines changed

src/ServiceStack.Text/Common/DeserializeType.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,16 @@ public static object ParseAbstractType<T>(string value)
120120

121121
public static object ParseQuotedPrimitive(string value)
122122
{
123-
if (string.IsNullOrEmpty(value)) return null;
123+
var fn = JsConfig.ParsePrimitiveFn;
124+
if (fn != null)
125+
{
126+
var result = fn(value);
127+
if (result != null)
128+
return result;
129+
}
130+
131+
if (string.IsNullOrEmpty(value))
132+
return null;
124133

125134
Guid guidValue;
126135
if (Guid.TryParse(value, out guidValue)) return guidValue;
@@ -160,10 +169,20 @@ public static object ParseQuotedPrimitive(string value)
160169

161170
public static object ParsePrimitive(string value)
162171
{
163-
if (string.IsNullOrEmpty(value)) return null;
172+
var fn = JsConfig.ParsePrimitiveFn;
173+
if (fn != null)
174+
{
175+
var result = fn(value);
176+
if (result != null)
177+
return result;
178+
}
179+
180+
if (string.IsNullOrEmpty(value))
181+
return null;
164182

165183
bool boolValue;
166-
if (bool.TryParse(value, out boolValue)) return boolValue;
184+
if (bool.TryParse(value, out boolValue))
185+
return boolValue;
167186

168187
// Parse as decimal
169188
decimal decimalValue;
@@ -219,8 +238,8 @@ internal static object ParsePrimitive(string value, char firstChar)
219238
if (typeof(TSerializer) == typeof(JsonTypeSerializer))
220239
{
221240
return firstChar == JsWriter.QuoteChar
222-
? ParseQuotedPrimitive(value)
223-
: ParsePrimitive(value);
241+
? ParseQuotedPrimitive(value)
242+
: ParsePrimitive(value);
224243
}
225244
return (ParsePrimitive(value) ?? ParseQuotedPrimitive(value));
226245
}

src/ServiceStack.Text/JsConfig.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,21 @@ public static Func<string, Type> TypeFinder
357357
}
358358
}
359359

360+
private static Func<string, object> sParsePrimitiveFn;
361+
public static Func<string, object> ParsePrimitiveFn
362+
{
363+
get
364+
{
365+
return (JsConfigScope.Current != null ? JsConfigScope.Current.ParsePrimitiveFn : null)
366+
?? sParsePrimitiveFn
367+
?? null;
368+
}
369+
set
370+
{
371+
if (sParsePrimitiveFn == null) sParsePrimitiveFn = value;
372+
}
373+
}
374+
360375
private static DateHandler? sDateHandler;
361376
public static DateHandler DateHandler
362377
{
@@ -738,6 +753,7 @@ public static void Reset()
738753
sJsvTypeAttrInObject = null;
739754
sTypeWriter = null;
740755
sTypeFinder = null;
756+
sParsePrimitiveFn = null;
741757
sTreatEnumAsInteger = null;
742758
sAlwaysUseUtc = null;
743759
sAssumeUtc = null;

src/ServiceStack.Text/JsConfigScope.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public void Dispose()
7070
internal string JsvTypeAttrInObject { get; set; }
7171
public Func<Type, string> TypeWriter { get; set; }
7272
public Func<string, Type> TypeFinder { get; set; }
73+
public Func<string, object> ParsePrimitiveFn { get; set; }
7374
public DateHandler? DateHandler { get; set; }
7475
public TimeSpanHandler? TimeSpanHandler { get; set; }
7576
public PropertyConvention? PropertyConvention { get; set; }

tests/ServiceStack.Text.Tests/DictionaryTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Specialized;
44
using System.Diagnostics;
55
using System.Globalization;
6+
using System.Text.RegularExpressions;
67
using NUnit.Framework;
78
using ServiceStack.Text.Tests.DynamicModels.DataModel;
89

@@ -627,6 +628,36 @@ private class ModelWithDictionary
627628
{
628629
public Dictionary<string, string> Value { get; set; }
629630
}
631+
632+
[Test]
633+
public void Do_not_convert_Guids()
634+
{
635+
JsConfig.DateHandler = DateHandler.ISO8601;
636+
JsConfig.AlwaysUseUtc = true;
637+
JsConfig.TryToParsePrimitiveTypeValues = true; // needed for datetime
638+
639+
var isGuidRegex =
640+
new Regex(@"^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$", RegexOptions.Compiled);
641+
642+
JsConfig.ParsePrimitiveFn = s => isGuidRegex.IsMatch(s) ? s : null;
643+
644+
var original = new Dictionary<string, object>
645+
{
646+
{"GuidString", "6A3F0923-A4B8-4026-9982-5C79128EA128"},
647+
{"DateTime", DateTime.UtcNow}
648+
};
649+
650+
var json = JsonSerializer.SerializeToString(original);
651+
652+
json.Print();
653+
654+
var deserialized = JsonSerializer.DeserializeFromString<Dictionary<string, object>>(json);
655+
656+
Assert.That(deserialized["GuidString"], Is.EqualTo("6A3F0923-A4B8-4026-9982-5C79128EA128"));
657+
Assert.That(deserialized["DateTime"], Is.AssignableTo(typeof(DateTime)));
658+
659+
JsConfig.Reset();
660+
}
630661
}
631662

632663
public class OrderedDictionarySub : OrderedDictionary { }

0 commit comments

Comments
 (0)