System.ArgumentOutOfRangeException 使用 Newtonsoft.Json 反序列化
System.ArgumentOutOfRangeException while deserializing using Newtonsoft.Json
我正在使用 Newtonsoft JSON 反序列化包含接口的对象。 Newtonsoft 在如何将接口映射到反序列化的具体类型方面遇到了问题 "figuring out",所以我按照 this answer 中的说明来解决问题。
我正在执行以下反序列化操作:
var converter = new JsonSerializer();
converter.Converters.Add(new DeviceCalibrationConverter());
// Obviously parameter.value and typeObj being the JSON and Type respectively
// I can see stepping through this that these are, in fact, the correct values
object deserialized = converter.Deserialize(new StringReader(parameter.Value), typeObj);
我正在使用 DeviceCalibrationConverter 对象尝试将我的接口映射到它的具体类型:
public class DeviceCalibrationConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// I am trying to map the IDeviceCalibration interface to its concrete type (DeviceCalibration)
return objectType.Equals(typeof(IDeviceCalibration));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize(reader, typeof(DeviceCalibration));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
我目前正在收到 "ArgumentOutOfRangeException." 完整异常详细信息如下:
System.ArgumentOutOfRangeException was unhandled
HResult=-2146233086
Message=Version's parameters must be greater than or equal to zero.
Parameter name: build
Source=mscorlib
ParamName=build
StackTrace:
at System.Version..ctor(Int32 major, Int32 minor, Int32 build, Int32 revision)
at Void .ctor(Int32, Int32, Int32, Int32)(Object[] )
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(TextReader reader, Type objectType)
at FunctionalTesting.ExecuteXMLScript.Execute() in [folder]\ExecuteXMLScript.cs:line 141
at FunctionalTesting.TestRunner.RunTests() in [folder]\TestRunner.cs:line 102
at FunctionalTesting.Program.Main(String[] args) in [folder]\Program.cs:line 43
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
顺便说一下,这发生在我尝试调用 Deserialize 的那一行。
编辑: 整个 JSON 相当冗长,但结果发现有问题的行如下:
{"State":"needs-translation","OriginalString":"LP","StringID":[id],"StringValue":"LP"}}],
"MarketingFeatures":null,
"CDIDriver" {"Name":"[Product Name]",
"Version":{"Major":1,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}}
特别是,在 "Version" 中反序列化为:
{"Major":1,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}
这反序列化为 System.Version class,这是无效的,因此产生了我上面列出的异常。
顺便说一句,CDIDriver 创建 Version 对象如下:
Version = new Version((int)major, (int)minor);
这是完全有效的,事实上,文档确实说按照描述使用此构造函数会将构建和修订设置为 -1(如 JSON 中所示)。那么我的问题是,如果这是一个完全有效的对象文档状态,为什么当我尝试反序列化它时它会产生这个异常?
我知道尝试执行 new Version(1, 0, -1, -1)
之类的操作会产生异常,这是记录在案的行为。 (这似乎是非常奇怪的行为,因为这会导致有效的对象状态,但这只是我的意见)。有什么办法可以做到:
new Version(1, 0, 0, 0)
只是为了反序列化工作?
Version
没有以正确的方式序列化。
如果操作正确,它应该是这样的:
{
...
"Version": "1.0"
}
这可以通过像这样使用 VersionConverter
来实现:
var json = JsonConvert.SerializeObject(new Version(1, 0), new VersionConverter());
反序列化也得用这个转换器:
var obj = JsonConvert.DeserializeObject<Version>(json, new VersionConverter());
工作示例:https://dotnetfiddle.net/eAqwip
请注意,您还可以使用 JsonConverterAttribute
注释 de/serialized class 以自动实现相同的目的:
public class DeviceCalibration
{
...
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; set }
}
如果您无法访问序列化程序代码,恐怕您将不得不修复 Json 字符串 "by hand" 或编写您自己的 VersionConverter
来处理-1
个值。
我正在使用 Newtonsoft JSON 反序列化包含接口的对象。 Newtonsoft 在如何将接口映射到反序列化的具体类型方面遇到了问题 "figuring out",所以我按照 this answer 中的说明来解决问题。
我正在执行以下反序列化操作:
var converter = new JsonSerializer();
converter.Converters.Add(new DeviceCalibrationConverter());
// Obviously parameter.value and typeObj being the JSON and Type respectively
// I can see stepping through this that these are, in fact, the correct values
object deserialized = converter.Deserialize(new StringReader(parameter.Value), typeObj);
我正在使用 DeviceCalibrationConverter 对象尝试将我的接口映射到它的具体类型:
public class DeviceCalibrationConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// I am trying to map the IDeviceCalibration interface to its concrete type (DeviceCalibration)
return objectType.Equals(typeof(IDeviceCalibration));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return serializer.Deserialize(reader, typeof(DeviceCalibration));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
我目前正在收到 "ArgumentOutOfRangeException." 完整异常详细信息如下:
System.ArgumentOutOfRangeException was unhandled
HResult=-2146233086
Message=Version's parameters must be greater than or equal to zero.
Parameter name: build
Source=mscorlib
ParamName=build
StackTrace:
at System.Version..ctor(Int32 major, Int32 minor, Int32 build, Int32 revision)
at Void .ctor(Int32, Int32, Int32, Int32)(Object[] )
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(TextReader reader, Type objectType)
at FunctionalTesting.ExecuteXMLScript.Execute() in [folder]\ExecuteXMLScript.cs:line 141
at FunctionalTesting.TestRunner.RunTests() in [folder]\TestRunner.cs:line 102
at FunctionalTesting.Program.Main(String[] args) in [folder]\Program.cs:line 43
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
顺便说一下,这发生在我尝试调用 Deserialize 的那一行。
编辑: 整个 JSON 相当冗长,但结果发现有问题的行如下:
{"State":"needs-translation","OriginalString":"LP","StringID":[id],"StringValue":"LP"}}],
"MarketingFeatures":null,
"CDIDriver" {"Name":"[Product Name]",
"Version":{"Major":1,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}}
特别是,在 "Version" 中反序列化为:
{"Major":1,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}
这反序列化为 System.Version class,这是无效的,因此产生了我上面列出的异常。
顺便说一句,CDIDriver 创建 Version 对象如下:
Version = new Version((int)major, (int)minor);
这是完全有效的,事实上,文档确实说按照描述使用此构造函数会将构建和修订设置为 -1(如 JSON 中所示)。那么我的问题是,如果这是一个完全有效的对象文档状态,为什么当我尝试反序列化它时它会产生这个异常?
我知道尝试执行 new Version(1, 0, -1, -1)
之类的操作会产生异常,这是记录在案的行为。 (这似乎是非常奇怪的行为,因为这会导致有效的对象状态,但这只是我的意见)。有什么办法可以做到:
new Version(1, 0, 0, 0)
只是为了反序列化工作?
Version
没有以正确的方式序列化。
如果操作正确,它应该是这样的:
{
...
"Version": "1.0"
}
这可以通过像这样使用 VersionConverter
来实现:
var json = JsonConvert.SerializeObject(new Version(1, 0), new VersionConverter());
反序列化也得用这个转换器:
var obj = JsonConvert.DeserializeObject<Version>(json, new VersionConverter());
工作示例:https://dotnetfiddle.net/eAqwip
请注意,您还可以使用 JsonConverterAttribute
注释 de/serialized class 以自动实现相同的目的:
public class DeviceCalibration
{
...
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; set }
}
如果您无法访问序列化程序代码,恐怕您将不得不修复 Json 字符串 "by hand" 或编写您自己的 VersionConverter
来处理-1
个值。