Skip to content

Commit 483321b

Browse files
committed
added option to throw on deserialization error"
1 parent 5b7a176 commit 483321b

5 files changed

Lines changed: 96 additions & 4 deletions

File tree

src/ServiceStack.Text/Common/DeserializeTypeRefJson.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ internal static object StringToType(
9393
}
9494
catch
9595
{
96-
Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
96+
if (JsConfig.ThrowOnDeserializationError) throw;
97+
else Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
9798
}
9899
}
99100

@@ -106,7 +107,8 @@ internal static object StringToType(
106107
}
107108
catch
108109
{
109-
Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
110+
if (JsConfig.ThrowOnDeserializationError) throw;
111+
else Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
110112
}
111113
}
112114

src/ServiceStack.Text/Common/DeserializeTypeRefJsv.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ internal static object StringToType(
8484
}
8585
catch
8686
{
87-
Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
87+
if (JsConfig.ThrowOnDeserializationError) throw;
88+
else Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
8889
}
8990
}
9091

@@ -97,7 +98,8 @@ internal static object StringToType(
9798
}
9899
catch
99100
{
100-
Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
101+
if (JsConfig.ThrowOnDeserializationError) throw;
102+
else Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
101103
}
102104
}
103105

src/ServiceStack.Text/JsConfig.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,29 @@ public static bool EmitCamelCaseNames
105105
}
106106
}
107107

108+
/// <summary>
109+
/// Gets or sets a value indicating if the framework should throw serialization exceptions
110+
/// or continue regardless of deserialization errors. If <see langword="true"/> the framework
111+
/// will throw; otherwise, it will parse as many fields as possible. The default is <see langword="false"/>.
112+
/// </summary>
113+
[ThreadStatic]
114+
private static bool? tsThrowOnDeserializationError;
115+
private static bool? sThrowOnDeserializationError;
116+
public static bool ThrowOnDeserializationError
117+
{
118+
// obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
119+
get
120+
{
121+
return tsThrowOnDeserializationError ?? sThrowOnDeserializationError ?? false;
122+
}
123+
set
124+
{
125+
bool theValue = value;
126+
if (!tsThrowOnDeserializationError.HasValue) tsThrowOnDeserializationError = value;
127+
if (!sThrowOnDeserializationError.HasValue) sThrowOnDeserializationError = value;
128+
}
129+
}
130+
108131
internal static HashSet<Type> HasSerializeFn = new HashSet<Type>();
109132

110133
public static void Reset()
@@ -114,6 +137,7 @@ public static void Reset()
114137
tsExcludeTypeInfo = sExcludeTypeInfo = null;
115138
tsEmitCamelCaseNames = sEmitCamelCaseNames = null;
116139
tsDateHandler = sDateHandler = null;
140+
tsThrowOnDeserializationError = sThrowOnDeserializationError = null;
117141
HasSerializeFn = new HashSet<Type>();
118142
}
119143

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using NUnit.Framework;
5+
using ServiceStack.Text.Tests.Support;
6+
7+
namespace ServiceStack.Text.Tests.JsonTests
8+
{
9+
[TestFixture]
10+
public class ThrowOnDeserializeErrorTest
11+
{
12+
13+
[Test]
14+
public void TestThrows()
15+
{
16+
JsConfig.Reset();
17+
JsConfig.ThrowOnDeserializationError = true;
18+
19+
string json = @"{""idBad"":""abc"", ""idGood"":""2"" }";
20+
21+
bool threw = false;
22+
try
23+
{
24+
JsonSerializer.DeserializeFromString(json, typeof(TestDto));
25+
}
26+
catch (Exception)
27+
{
28+
threw = true;
29+
}
30+
31+
Assert.IsTrue(threw, "Should have thrown");
32+
}
33+
34+
[Test]
35+
public void TestDoesNotThrow()
36+
{
37+
JsConfig.Reset();
38+
JsConfig.ThrowOnDeserializationError = false;
39+
string json = @"{""idBad"":""abc"", ""idGood"":""2"" }";
40+
JsonSerializer.DeserializeFromString(json, typeof(TestDto));
41+
}
42+
43+
[Test]
44+
public void TestReset()
45+
{
46+
JsConfig.Reset();
47+
Assert.IsFalse(JsConfig.ThrowOnDeserializationError);
48+
JsConfig.ThrowOnDeserializationError = true;
49+
Assert.IsTrue(JsConfig.ThrowOnDeserializationError);
50+
JsConfig.Reset();
51+
Assert.IsFalse(JsConfig.ThrowOnDeserializationError);
52+
}
53+
54+
[DataContract]
55+
class TestDto
56+
{
57+
[DataMember(Name = "idGood")]
58+
public int IdGood { get; set; }
59+
[DataMember(Name = "idBad")]
60+
public int IdBad { get; set; }
61+
}
62+
}
63+
}

tests/ServiceStack.Text.Tests/ServiceStack.Text.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
<Compile Include="CsvTests\CustomHeaderTests.cs" />
176176
<Compile Include="JsonTests\JsonDateTimeTests.cs" />
177177
<Compile Include="JsonTests\PolymorphicListTests.cs" />
178+
<Compile Include="JsonTests\ThrowOnDeserializeErrorTest.cs" />
178179
<Compile Include="JsvTests\JsvDeserializeTypeTest.cs" />
179180
<Compile Include="MessagingTests.cs" />
180181
<Compile Include="NullableTypesTests.cs" />

0 commit comments

Comments
 (0)