在我的项目中测试并调试了一个级别生成器后,我从Unity3d中使用JSON.Net发生了一个奇怪的错误,该级别生成器从资源中读取文件并将文件写入桌面。生成器读取json文件的特定部分,这可以正常工作。在从统一编辑器崩溃时,同时对数据进行序列化和反序列化以及对旧数据进行异步处理。
由于崩溃,Json.Net在反序列化文件的一部分时给出错误。看起来Json.Net不再识别冒号了。我收到以下错误:
JsonSerializationException: Unexpected token while deserializing object: PropertyName. Path 'Levels', line 2, position 12.
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) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.Linq.JToken.ToObject (System.Type objectType, Newtonsoft.Json.JsonSerializer jsonSerializer) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.Linq.JToken.ToObject (System.Type objectType) (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
Newtonsoft.Json.Linq.JToken.ToObject[T] () (at <97722d3abc9f4cf69f9e21e6770081b3>:0)
JsonHelper+<GetCollection>d__3`1[T].MoveNext () (at Assets/Scripts/Utils/JsonHelper.cs:25)
{
"Levels":[
],
"DefaultConfig":{
"FieldSize":{
"Height":25,
"Width":27
},
"FieldBlocks":{
"BlockScale":3,
"CenterTop":10,
"FieldTop":9
}
}
}
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System;
public static class JsonHelper
{
private static JObject jsonRoot;
public static void InitializeJsonHelper(string json)
{
jsonRoot = JObject.Parse(json);
}
public static async Task<T> GetObjectFromJson<T>(string section)
{
JToken token = await FindTokenWithSectionName(section);
return token.ToObject<T>();
}
public static async Task<List<T>> GetCollection<T>(string section)
{
JToken token = await FindTokenWithSectionName(section);
return token.ToObject<List<T>>();
}
public static async Task<string> AddCollectionToSection<T>(ICollection<T> objects, string section)
{
try
{
JProperty currentProperty = await FindTokenWithSectionName(section);
JProperty newProperty = new JProperty(currentProperty);
/*var objectsAsJson = JsonConvert.SerializeObject(objects);
newProperty.Value = JToken.Parse(objectsAsJson);*/
currentProperty.Replace(newProperty);
await SetReplaceTokenToSection(currentProperty, section);
return jsonRoot.ToString();
}
catch (Exception exception)
{
return exception.StackTrace;
}
}
public static async Task<string>AddObjectToSection<T>(T newObject, string section)
{
JToken token = await FindTokenWithSectionName(section);
JValue valueOfToken = new JValue(newObject);
token.Replace(valueOfToken);
await SetReplaceTokenToSection(token, section);
return jsonRoot.ToString();
}
private static async Task<JProperty> FindTokenWithSectionName(string section)
{
return await Task.Run(() =>
{
JProperty property = jsonRoot.Property(section);
return property;
});
}
private static Task SetReplaceTokenToSection(JToken newToken, string section)
{
JProperty property = jsonRoot.Property(section);
property.Value = newToken;
return Task.CompletedTask;
}
}
如何解决错误?
答案 0 :(得分:2)
您的问题是您正在尝试将JProperty
反序列化为某些内容。相反,您需要反序列化其value:
public static async Task<T> GetObjectFromJson<T>(string section)
{
JProperty token = await FindTokenWithSectionName(section);
return token.Value.ToObject<T>(); // What to do if token is null?
}
public static async Task<List<T>> GetCollection<T>(string section)
{
JProperty token = await FindTokenWithSectionName(section);
return token.Value.ToObject<List<T>>(); // What to do if token is null?
}
JProperty
代表JObject
中的命名值;您想反序列化值本身。
偶然地,我没有看到使FindTokenWithSectionName()
异步运行的理由。 JToken
层次结构是某些JSON的内存表示形式,因此将不执行I / O,而JObject.Property(string name)
只是dictionary lookup,因此应该很快。而且,如果JsonHelper
是诸如数据库查找之类的慢速对象的模型,那么我就不会期望该类是静态的,因为静态类不适合用于依赖项注入。
此外,在静态类中使用静态字段来捕获某些运行时加载的JSON看起来可能是线程不安全的。
演示小提琴here。