作为我为Android开发的Xamarin Forms应用程序的一部分,我有一个Json配置文件,其中保存了一些设置,比如该应用程序是否处于调试模式,或者用户登录网站等。
然而,试图从Json文件获取此用户对象会引发上述异常,下面也可以看到完整的异常。
EXCEPTION 10-02-2020 14:06:08 Newtonsoft.Json.JsonSerializationException => Error converting value "{
"$type": "Dental.App.Models.User, Dental.App",
"username": "Ole",
"password": "ole",
"verifiedStatus": false,
"creationTime": "10-02-2020 13:35:13"
}" to type 'Dental.App.Models.User'. Path 'User', line 5, position 197.; Stacktrace => at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType (Newtonsoft.Json.JsonReader reader, System.Object value, System.Globalization.CultureInfo culture, Newtonsoft.Json.Serialization.JsonContract contract, System.Type targetType) [0x000bd] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x000d7] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue (Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, System.Object target) [0x00061] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) [0x00267] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00154] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000d9] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00053] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <f393073e86a643d9809b1a5d0c498495>:0
at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <f393073e86a643d9809b1a5d0c498495>:0
at Wolf.Utility.Main.Transport.JsonManipulator.ReadValueViaModel[T,U] (System.String path, System.String propertyName) [0x000c8] in <46eeb80ce9a440109e5bc07b0f1af244>:0
at Dental.App.Config.get_User () [0x00013] in <c94e9f8f60b14ec69bd9794bdf834717>:0
at Dental.App.Views.DentalWebPage.DentalWebView_LoadFinished (System.Object sender, System.EventArgs e) [0x00035] in <c94e9f8f60b14ec69bd9794bdf834717>:0
我试图反序列化的User和ConfigModel对象非常简单。它们可以在下面看到,以及我的Config文件的一部分,其中包含我存储在Json中的一些属性,然后是我的Json。
public class User
{
[JsonProperty("username")]
public string Username { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
[JsonProperty("verifiedStatus")]
public bool VerifiedStatus { get; set; }
[JsonProperty("creationTime")]
public string CreationTime { get; private set; }
[JsonIgnore]
public DateTime TimeOfCreation => Convert.ToDateTime(CreationTime);
public User()
{
CreationTime = DateTime.Now.ToString(CultureInfo.CurrentCulture);
}
[JsonConstructor]
public User(string creationTime)
{
CreationTime = creationTime;
}
}
public class ConfigModel
{
public User User { get; set; }
}
public class Config
{
private static User user = new User();
public static User User
{
get => CanSave ? JsonManipulator.ReadValueViaModel<User, ConfigModel>(ConfigPath, nameof(User)) : user;
set
{
if (CanSave) JsonManipulator.WriteValue(ConfigPath, nameof(User), value);
else user = value;
}
}
private static bool debugMode = true;
public static bool DebugMode
{
get => CanSave ? JsonManipulator.ReadValue<bool>(ConfigPath, nameof(DebugMode)) : debugMode;
set
{
if (CanSave) JsonManipulator.WriteValue(ConfigPath, nameof(DebugMode), value);
else debugMode = value;
}
}
...
}
{
"DebugMode": "true",
"UseCustomOptions": "false",
"CustomFormats": "{\n \"$type\": \"System.Collections.Generic.List`1[[ZXing.BarcodeFormat, zxing.portable]], mscorlib\",\n \"$values\": []\n}",
"User": "{\n \"$type\": \"Dental.App.Models.User, Dental.App\",\n \"username\": \"Ole\",\n \"password\": \"ole\",\n \"verifiedStatus\": false,\n \"creationTime\": \"10-02-2020 13:35:13\"\n}",
"SelectedMenu": "3"
}
对于这个过程,我的代码中完成工作的部分来自我的实用程序库。此库是我的github上的一个子模块,可以在以下位置找到完整的库:https://github.com/andr9528/Wolf.Utility.Main
下面是我的JsonManipulator类中的方法,该类在尝试反序列化到User对象时抛出所提到的异常,即T是User。有关完整课程,请访问上面的链接。
public class JsonManipulator
{
/// <summary>
/// Parses Json file, and returns the attribute specified by 'propertyName'.
/// </summary>
/// <typeparam name="T">The type returned, from the property named after the input 'propertyName'.</typeparam>
/// <param name="path">Path of the Json file.</param>
/// <param name="propertyName">Name of the property to return.</param>
/// <returns></returns>
public static T ReadValue<T>(string path, string propertyName)
{
if (!File.Exists(path))
throw new ArgumentNullException(nameof(path), $@"No file Exist on the specified path => {path}");
if (path.Split('.').Last().ToLowerInvariant() != "json")
throw new ArgumentException("The path given did not end in 'json'");
var json = File.ReadAllText(path);
try
{
var obj = JObject.Parse(json);
if (obj != null)
return obj[propertyName].ToObject<T>();
throw new OperationFailedException($"Failed to parse Json from the file located at => {path}");
}
catch (Exception ex)
{
throw;
}
}
/// <summary>
/// Deserializes Json file into specified model, and returns the property from it by the value specified in 'propertyName'.
/// </summary>
/// <typeparam name="T">The type returned, from the property named after the input 'propertyName'.</typeparam>
/// <typeparam name="U">The model that is deserialized into, and from which the property is taken and returned.</typeparam>
/// <param name="path">Path of the Json file.</param>
/// <param name="propertyName">Name of the property to return.</param>
/// <returns></returns>
public static T ReadValueViaModel<T, U>(string path, string propertyName)
{
if (!File.Exists(path))
throw new ArgumentNullException(nameof(path), $@"No file Exist on the specified path => {path}");
if (path.Split('.').Last().ToLowerInvariant() != "json")
throw new ArgumentException("The path given did not end in 'json'");
var json = File.ReadAllText(path);
try
{
var obj = JsonConvert.DeserializeObject<U>(json, new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.All
});
var prop = obj.GetType().GetProperties().First(x => x.Name == propertyName);
return (T)prop.GetValue(obj);
}
catch (Exception)
{
throw;
}
}
...
}
只有我的配置中的User属性的Get部分存在此问题,我需要调用它来获取包含用户名和密码的User对象。
为了尝试解决这个问题,我做了一些更改,这些都可以在上面的代码中看到。下面是一些示例(如果不是全部的话)。
>
将JsonProperty规范添加到用户对象的属性中
在用户对象上添加了JsonConstructor
已将用户对象的属性“CreationTime”的类型从DateTime更改为string。
在JsonManipulator中与ConfigModel类一起创建了ReadValueViaModel方法
我有一种恼人的感觉,我所缺少的只是某个地方的一小段代码或格式,但我根本不知道我在哪里以及缺少了什么才能让它工作。
可以随时向我提问以清除任何缺失的信息。
编辑1:更新的Json格式-直接从自动生成的Json文件复制。根据https://jsonlint.com/,它是有效的Json,因此我的WriteValue方法正在创建有效的Json。
您这样做似乎是因为您不知道库的某些特性。这是最常用的库之一(Microsoft在大多数基于web的项目类型中默认都包含了它)-请先看看库的功能,然后再疯狂地尝试重新发明它的功能。
这是之前的堆栈溢出问题:JSON. net缺少属性的默认值
下面是一个代码示例:
void Main()
{
string testJSON = @"[{""FirstName"":""Michael"",""LastName"":""Jones""},{""FirstName"":""Jon"",""LastName"":""Smith""}]";
PersonModel[] people = JsonConvert.DeserializeObject<PersonModel[]>(testJSON);
people.Dump();
}
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string GUID { get; set; }
[DefaultValue(100)] //lets be generous when starting our loyalty program!
[JsonProperty("LoyaltyPoints", DefaultValueHandling = DefaultValueHandling.Populate)]
public int LoyaltyPoints { get; set; }
}
下面是垃圾场的屏幕截图:
更新:
你还没有给出一个很好的理由来按照你现在的方式做事。与其存储包含字符串化JSON对象的JSON对象,不如存储如下内容:
{
"DebugMode": "true",
"UseCustomOptions": "false",
"SelectedMenu": "3",
"CustomFormats": [],
"User": {
"username": "Ole",
"password": "ole",
"verifiedStatus": "false",
"creationTime": "10-02-2020 13:35:13"
}
}
您的模型应该如下所示(显然我在这里有点猜测,因为您没有发布所有代码):
public class Config
{
public bool DebugMode { get; set; }
public bool UseCustomOptions { get; set; }
public int SelectedMenu { get; set; }
public List<ZXing.BarcodeFormat> CustomFormats { get; set; }
public User User { get; set; }
}
public class User
{
public string Username { get; set; }
public string Password { get; set; }
public bool VerifiedStatus { get; set; }
public DateTime CreationTime { get; set; }
}
void Main()
{
//and then you can just ...
string myJsonString = "...";
Config config = JsonConvert.DeserializeObject<Config>(myJsonString);
}
我尝试反序列化一个巨大的API负载。这个有效负载包含的字段比我需要的要多,因此我正在使用。但是,在某些情况下,反序列化会失败,并显示错误消息: 我找到了解决方案,建议使用 我试过这个。但这于事无补。此外,我的结果数据不是一个单一的值数组。它实际上包含两个值——因此解决方案无论如何都不会相加。 以下是反序列化的目标类。 下面是我测试它的单元测试: 这是我想要反序列化的有效负载
为了确保在我的RESTful web服务中来回发送的数据不冗余,每个嵌套对象都只序列化了它的ID(消息的用户只序列化了用户ID,因为客户端和服务器都已经知道用户的所有详细信息)。 序列化工作正常,产生以下效果: 问题:反序列化不会生成仅具有其ID的嵌套对象。生成的反序列化嵌套对象为空。 以下是前面提到的消息和用户对象。序列化“策略”是从此处指定的第三个选项中使用的:如何仅序列化Jackson的子级
我试图获取我的Web请求JSON输出并解析它。这是输出 我为这些结果创建了公共课程 当我尝试反序列化Record类并选择名称时,我从RootObject类获得名称。这是我的密码
问题内容: 我尝试反序列化包含null属性并具有的对象。 我做的事: 但是 :如果扔掉财产-一切正常!我的意思是传递下一个字符串: 问题 :如何避免此异常或保证杰克逊在序列化期间忽略空值? 抛出: 信息: 原因: 原因: 问题答案: 如果您不想序列化值,则可以使用以下设置(序列化期间): 希望这能解决您的问题。 但是反序列化过程中获得的结果对我来说似乎很可疑(理想情况下,杰克逊应该能够处理序列化输
问题内容: 我有一堂课POJO 我有一个像 我正在使用Jackson ObjectMapper进行反序列化。在不创建任何其他父类的情况下如何获得? 如果不可能,是否有可能获得仅包含json字符串的第一个元素的对象,即在这种情况下和? 问题答案: 您首先需要获取数组 打印(带有)
我需要在PlayFramework中从Json创建object。 你们有什么建议吗? 谢谢!!