Я использую Newtonsoft JSON для десериализации объекта, содержащего интерфейсы. У Newtonsoft возникли проблемы с «выяснением», как сопоставить интерфейсы с их конкретными типами при десериализации, поэтому я исправил проблему в this answer.System.ArgumentOutOfRangeException при десериализации с использованием Newtonsoft.Json
Я делаю следующее десериализовать:
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:
Это происходит, кстати, на линии, где я пытаюсь позвонить десериализации.
Edit: Весь 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}}
В частности, в "Версии" десериализует к:
{"Major":1,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}
Этот десериализуется класс System.Version, и это недействительно, таким образом, создавая исключение, указанное выше.
CDIDriver, кстати, создает объект Version следующим образом:
Version = new Version((int)major, (int)minor);
Это вполне допустимо, и документ делает, на самом деле, сказать, что с помощью этого конструктора, как описано установит сборку и пересмотр до -1 (как показано в JSON). Тогда мой вопрос заключается в том, является ли это вполне допустимым, состояние документа объекта, почему оно создает это исключение, когда я пытаюсь десериализовать его?
Я знаю, что попытка сделать что-то вроде new Version(1, 0, -1, -1)
приведет к исключению и что это документированное поведение. (Это похоже на очень странное поведение, учитывая, что это приведет к действительному состоянию объекта, но это только мое мнение). Есть ли какой-то способ:
new Version(1, 0, 0, 0)
только ради проведения десериализации?
Первое, что я хотел бы сделать, это избавиться от XML из уравнения. Похоже, вы должны быть в состоянии предоставить [mcve] без каких-либо XML вообще. –
@JonSkeet Вы имеете в виду от моего поста или от моего решения? (Прямо сейчас, лучше или хуже, я должен использовать XML как часть самого решения). – EJoshuaS
Просто со своего поста, чтобы изолировать проблему. Решение проблем с программным обеспечением в основном связано с устранением нерелевантных аспектов, пока вы не увидите только один проблемный бит. –