Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/ServiceStack.Text/Common/DeserializeTypeRefJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ internal static object StringToType(
}
catch
{
Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
if (JsConfig.ThrowOnDeserializationError) throw;
else Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
}
}

Expand All @@ -106,7 +107,8 @@ internal static object StringToType(
}
catch
{
Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
if (JsConfig.ThrowOnDeserializationError) throw;
else Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/ServiceStack.Text/Common/DeserializeTypeRefJsv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ internal static object StringToType(
}
catch
{
Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
if (JsConfig.ThrowOnDeserializationError) throw;
else Tracer.Instance.WriteWarning("WARN: failed to set dynamic property {0} with: {1}", propertyName, propertyValueStr);
}
}

Expand All @@ -97,7 +98,8 @@ internal static object StringToType(
}
catch
{
Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
if (JsConfig.ThrowOnDeserializationError) throw;
else Tracer.Instance.WriteWarning("WARN: failed to set property {0} with: {1}", propertyName, propertyValueStr);
}
}

Expand Down
9 changes: 8 additions & 1 deletion src/ServiceStack.Text/Common/WriteType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,14 @@ public static void WriteProperties(TextWriter writer, object value)
writer.Write(JsWriter.MapKeySeperator);

if (typeof (TSerializer) == typeof (JsonTypeSerializer)) JsState.IsWritingValue = true;
propertyWriter.WriteFn(writer, propertyValue);
if (propertyValue == null)
{
writer.Write(JsonUtils.Null);
}
else
{
propertyWriter.WriteFn(writer, propertyValue);
}
if (typeof(TSerializer) == typeof(JsonTypeSerializer)) JsState.IsWritingValue = false;
}
}
Expand Down
24 changes: 24 additions & 0 deletions src/ServiceStack.Text/JsConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,29 @@ public static bool EmitCamelCaseNames
}
}

/// <summary>
/// Gets or sets a value indicating if the framework should throw serialization exceptions
/// or continue regardless of deserialization errors. If <see langword="true"/> the framework
/// will throw; otherwise, it will parse as many fields as possible. The default is <see langword="false"/>.
/// </summary>
[ThreadStatic]
private static bool? tsThrowOnDeserializationError;
private static bool? sThrowOnDeserializationError;
public static bool ThrowOnDeserializationError
{
// obeying the use of ThreadStatic, but allowing for setting JsConfig once as is the normal case
get
{
return tsThrowOnDeserializationError ?? sThrowOnDeserializationError ?? false;
}
set
{
bool theValue = value;
if (!tsThrowOnDeserializationError.HasValue) tsThrowOnDeserializationError = value;
if (!sThrowOnDeserializationError.HasValue) sThrowOnDeserializationError = value;
}
}

internal static HashSet<Type> HasSerializeFn = new HashSet<Type>();

public static void Reset()
Expand All @@ -114,6 +137,7 @@ public static void Reset()
tsExcludeTypeInfo = sExcludeTypeInfo = null;
tsEmitCamelCaseNames = sEmitCamelCaseNames = null;
tsDateHandler = sDateHandler = null;
tsThrowOnDeserializationError = sThrowOnDeserializationError = null;
HasSerializeFn = new HashSet<Type>();
}

Expand Down
12 changes: 10 additions & 2 deletions tests/ServiceStack.Text.Tests/JsonTests/BasicJsonTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,19 @@ public void Serialize_can_include_null_values()
Type = "Programmer",
SampleKey = 12,
Nothing = null,
NullableDateTime = null
NullableDateTime = null,
NullClass = null
};

JsConfig.IncludeNullValues = true;
var s = JsonSerializer.SerializeToString(o);
JsConfig.Reset();
Assert.That(s, Is.EqualTo("{\"Name\":\"Brandon\",\"Type\":\"Programmer\",\"SampleKey\":12,\"Nothing\":null,\"NullableDateTime\":null}"));
Assert.That(s, Is.EqualTo("{\"Name\":\"Brandon\",\"Type\":\"Programmer\",\"SampleKey\":12,\"Nothing\":null,\"NullableDateTime\":null,\"NullClass\":null}"));
}

private class NullClass
{

}

[Test]
Expand Down Expand Up @@ -153,6 +159,8 @@ public string Nothing
set;
}

public NullClass NullClass { get; set; }

public DateTime? NullableDateTime { get; set; }

public NullValueTester()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using NUnit.Framework;
using ServiceStack.Text.Tests.Support;

namespace ServiceStack.Text.Tests.JsonTests
{
[TestFixture]
public class ThrowOnDeserializeErrorTest
{

[Test]
public void TestThrows()
{
JsConfig.Reset();
JsConfig.ThrowOnDeserializationError = true;

string json = @"{""idBad"":""abc"", ""idGood"":""2"" }";

bool threw = false;
try
{
JsonSerializer.DeserializeFromString(json, typeof(TestDto));
}
catch (Exception)
{
threw = true;
}

Assert.IsTrue(threw, "Should have thrown");
}

[Test]
public void TestDoesNotThrow()
{
JsConfig.Reset();
JsConfig.ThrowOnDeserializationError = false;
string json = @"{""idBad"":""abc"", ""idGood"":""2"" }";
JsonSerializer.DeserializeFromString(json, typeof(TestDto));
}

[Test]
public void TestReset()
{
JsConfig.Reset();
Assert.IsFalse(JsConfig.ThrowOnDeserializationError);
JsConfig.ThrowOnDeserializationError = true;
Assert.IsTrue(JsConfig.ThrowOnDeserializationError);
JsConfig.Reset();
Assert.IsFalse(JsConfig.ThrowOnDeserializationError);
}

[DataContract]
class TestDto
{
[DataMember(Name = "idGood")]
public int IdGood { get; set; }
[DataMember(Name = "idBad")]
public int IdBad { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
<Compile Include="CsvTests\CustomHeaderTests.cs" />
<Compile Include="JsonTests\JsonDateTimeTests.cs" />
<Compile Include="JsonTests\PolymorphicListTests.cs" />
<Compile Include="JsonTests\ThrowOnDeserializeErrorTest.cs" />
<Compile Include="JsvTests\JsvDeserializeTypeTest.cs" />
<Compile Include="MessagingTests.cs" />
<Compile Include="NullableTypesTests.cs" />
Expand Down