在Unity中使用NewtonJson时,如果要序列化的类继承了别的类,可能报如下错误:
JsonSerializationException: Self referencing loop detected for property......
解决的方法是新建一个JsonSerializerSettings对象,并设置对象的ReferenceLoopHandling参数为:ReferenceLoopHandling.Ignore,然后在序列化时将这个对象作为参数添加进去。参考如下:
var settings = new JsonSerializerSettings();
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string json = JsonConvert.SerializeObject(infos, settings);
如果我们要序列化一个基类的数组,由于子类可能会出现参数相同,但是类型不同的问题,最好在JsonSerializerSettings对象里面设置TypeNameHandling的值为TypeNameHandling.Auto,这样NewtonJson序列化时会在必要的情况下添加对象的类型信息。参考如下:
var settings = new JsonSerializerSettings();
settings.TypeNameHandling = TypeNameHandling.Auto;
settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
string json = JsonConvert.SerializeObject(infos, settings);
序列化的结果参考如下:
[{"$type": "BoxColliderInfo, Assembly-CSharp","size": {"x": 1.0,"y": 1.0,"z": 1.0,"normalized": {"x": 0.577350259,"y": 0.577350259,"z": 0.577350259,"magnitude": 1.0,"sqrMagnitude": 0.99999994},"magnitude": 1.73205078,"sqrMagnitude": 3.0},"center": {"x": 0.0,"y": 1.0,"z": 0.0,"magnitude": 1.0,"sqrMagnitude": 1.0},"cip": "0"},{"$type": "SphereColliderInfo, Assembly-CSharp","radius": 2.5,"center": {"x": 1.0,"y": 0.0,"z": 0.0,"magnitude": 1.0,"sqrMagnitude": 1.0},"cip": "1"}
]
需要注意的是,这里面添加了"$type"字段,这是为了在反序列化是能得到正确类型的对象。
最后需要说的是,在序列化和反序列化时应该使用相同的JsonSerializerSettings对象设置。于是我写了一个类来简化使用NewtonJson的代码,参考如下:
using Newtonsoft.Json;public class JsonTool
{static JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, ReferenceLoopHandling = ReferenceLoopHandling.Ignore};public static string ToJson(object obj) { return JsonConvert.SerializeObject(obj, settings);}public static T FromJson<T>(string json) { return JsonConvert.DeserializeObject<T>(json, settings); }
}
现在,我们使用JsonTool.ToJson和JsonTool.FromJson就可以了。
如果你之前使用的是Unity内置的JsonUtility,现在直接用JsonTool搜索并替换JsonUtility就可以了。