ServiceStack TypeSerializer.DeserializeFromString C# 可空类型的错误
ServiceStack TypeSerializer.DeserializeFromString bug with C# nullable types
似乎 ServiceStack 方法 TypeSerializer.DeserializeFromString 中存在关于可空类型的错误
这是一个已知问题吗?
是否有修复或解决方法?
考虑以下代码,其中包含一个 JsConfig 范围,该范围在任何反序列化错误时强制抛出异常:
public class MeasurementsData
{
public int? FlowLeft { get; set; }
public int? FlowRight { get; set; }
public Single? RatioLeft { get; set; }
public Single? RatioRight { get; set; }
}
.
.
.
var originalData = "{FlowRight:970045,RatioRight:null}";
object afterConversionData = null;
try
{
using (var scope = JsConfig.BeginScope())
{
scope.ThrowOnDeserializationError = true;
afterConversionData =TypeSerializer.DeserializeFromString(originalData.ToString() ,typeof(MeasurementsData));
}
}
catch (System.Runtime.Serialization.SerializationException ex)
{
Logger.Warn("Service exception", ex);
}
varaible originalData里面的json导致异常(详见下文)"Failed to set property 'RatioRight' with 'null'"。
尽管 'RatioRight' 是 'nullable single' 且 'null' 是有效值,但仍会发生这种情况。
删除 scope.ThrowOnDeserializationError = true
"works" 但我们不是一个选择,因为我们需要验证在服务器端收到的数据。
我会解释一下,如果我们将 ThrowOnDeserializationError
设置为 false(这是默认设置),在这种特定情况下不会抛出错误,但它会允许发送 json 像这样:{FlowRight:970045,RatioRight:fdfd}
DeserializeFromString 的结果不会抛出异常,尽管 'fdfd' 不是可空的单例。会发生什么情况是,异常将在内部处理并设置为 null,导致服务器不知道发送的数据是无效的,并且稍后会导致保存空值而不是数据库中已有的值(如我提到过,我们不能接受)
异常:
来源:ServiceStack.Text
Exception: Failed to set property 'MeasurementData' with '{FlowRight:970045,RatioRight:null}'
InnerException: Failed to set property 'RatioRight' with 'null'
StackTrace:
at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(TypeConfig typeConfig, String strType, EmptyCtorDelegate ctorFn, Dictionary'2 typeAccessorMap)
at ServiceStack.Text.Common.DeserializeType'1.<>c__DisplayClass3.b__2(String value)
at ServiceStack.Text.TypeSerializer.DeserializeFromString(String value, Type type)
at Site.Service.Services.DataDomainService.Any(SaveDataDomainRequest request) in D:\Service\API Services\Domain\Services\DataDomainService.cs:line 93
ServiceStack.Text 的 TypeSerializer 使用 JSV Format,后者使用 CSV 转义,因此 null
值被视为无法转换为的 "null"
字符串一个数字,导致错误。
要保留默认值,它应该从 JSV 发出,例如:
var originalData = "{FlowRight:970045}";
如果您正在寻找 JSON 序列化器,您应该使用 JsonSerializer
,例如:
var afterConversionData = JsonSerializer.DeserializeFromString(
originalData.ToString(), typeof(MeasurementsData));
可以使用扩展方法更简洁地重写,例如:
var object = originalData.ToString().FromJson<MeasurementsData>();
似乎 ServiceStack 方法 TypeSerializer.DeserializeFromString 中存在关于可空类型的错误
这是一个已知问题吗? 是否有修复或解决方法?
考虑以下代码,其中包含一个 JsConfig 范围,该范围在任何反序列化错误时强制抛出异常:
public class MeasurementsData
{
public int? FlowLeft { get; set; }
public int? FlowRight { get; set; }
public Single? RatioLeft { get; set; }
public Single? RatioRight { get; set; }
}
.
.
.
var originalData = "{FlowRight:970045,RatioRight:null}";
object afterConversionData = null;
try
{
using (var scope = JsConfig.BeginScope())
{
scope.ThrowOnDeserializationError = true;
afterConversionData =TypeSerializer.DeserializeFromString(originalData.ToString() ,typeof(MeasurementsData));
}
}
catch (System.Runtime.Serialization.SerializationException ex)
{
Logger.Warn("Service exception", ex);
}
varaible originalData里面的json导致异常(详见下文)"Failed to set property 'RatioRight' with 'null'"。 尽管 'RatioRight' 是 'nullable single' 且 'null' 是有效值,但仍会发生这种情况。
删除 scope.ThrowOnDeserializationError = true
"works" 但我们不是一个选择,因为我们需要验证在服务器端收到的数据。
我会解释一下,如果我们将 ThrowOnDeserializationError
设置为 false(这是默认设置),在这种特定情况下不会抛出错误,但它会允许发送 json 像这样:{FlowRight:970045,RatioRight:fdfd}
DeserializeFromString 的结果不会抛出异常,尽管 'fdfd' 不是可空的单例。会发生什么情况是,异常将在内部处理并设置为 null,导致服务器不知道发送的数据是无效的,并且稍后会导致保存空值而不是数据库中已有的值(如我提到过,我们不能接受)
异常:
来源:ServiceStack.Text
Exception: Failed to set property 'MeasurementData' with '{FlowRight:970045,RatioRight:null}' InnerException: Failed to set property 'RatioRight' with 'null'
StackTrace: at ServiceStack.Text.Common.DeserializeTypeRefJsv.StringToType(TypeConfig typeConfig, String strType, EmptyCtorDelegate ctorFn, Dictionary'2 typeAccessorMap) at ServiceStack.Text.Common.DeserializeType'1.<>c__DisplayClass3.b__2(String value) at ServiceStack.Text.TypeSerializer.DeserializeFromString(String value, Type type) at Site.Service.Services.DataDomainService.Any(SaveDataDomainRequest request) in D:\Service\API Services\Domain\Services\DataDomainService.cs:line 93
ServiceStack.Text 的 TypeSerializer 使用 JSV Format,后者使用 CSV 转义,因此 null
值被视为无法转换为的 "null"
字符串一个数字,导致错误。
要保留默认值,它应该从 JSV 发出,例如:
var originalData = "{FlowRight:970045}";
如果您正在寻找 JSON 序列化器,您应该使用 JsonSerializer
,例如:
var afterConversionData = JsonSerializer.DeserializeFromString(
originalData.ToString(), typeof(MeasurementsData));
可以使用扩展方法更简洁地重写,例如:
var object = originalData.ToString().FromJson<MeasurementsData>();