当前位置:   article > 正文

Unity中使用NewtonJson序列化继承类时报错解决方法参考_jsonserializationexception: self referencing loop

jsonserializationexception: self referencing loop detected for property 'nor

        在Unity中使用NewtonJson时,如果要序列化的类继承了别的类,可能报如下错误:

JsonSerializationException: Self referencing loop detected for property......

        解决的方法是新建一个JsonSerializerSettings对象,并设置对象的ReferenceLoopHandling参数为:ReferenceLoopHandling.Ignore,然后在序列化时将这个对象作为参数添加进去。参考如下:

  1. var settings = new JsonSerializerSettings();
  2. settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  3. string json = JsonConvert.SerializeObject(infos, settings);

        如果我们要序列化一个基类的数组,由于子类可能会出现参数相同,但是类型不同的问题,最好在JsonSerializerSettings对象里面设置TypeNameHandling的值为TypeNameHandling.Auto,这样NewtonJson序列化时会在必要的情况下添加对象的类型信息。参考如下:

  1. var settings = new JsonSerializerSettings();
  2. settings.TypeNameHandling = TypeNameHandling.Auto;
  3. settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  4. string json = JsonConvert.SerializeObject(infos, settings);

        序列化的结果参考如下:

  1. [
  2. {
  3. "$type": "BoxColliderInfo, Assembly-CSharp",
  4. "size": {
  5. "x": 1.0,
  6. "y": 1.0,
  7. "z": 1.0,
  8. "normalized": {
  9. "x": 0.577350259,
  10. "y": 0.577350259,
  11. "z": 0.577350259,
  12. "magnitude": 1.0,
  13. "sqrMagnitude": 0.99999994
  14. },
  15. "magnitude": 1.73205078,
  16. "sqrMagnitude": 3.0
  17. },
  18. "center": {
  19. "x": 0.0,
  20. "y": 1.0,
  21. "z": 0.0,
  22. "magnitude": 1.0,
  23. "sqrMagnitude": 1.0
  24. },
  25. "cip": "0"
  26. },
  27. {
  28. "$type": "SphereColliderInfo, Assembly-CSharp",
  29. "radius": 2.5,
  30. "center": {
  31. "x": 1.0,
  32. "y": 0.0,
  33. "z": 0.0,
  34. "magnitude": 1.0,
  35. "sqrMagnitude": 1.0
  36. },
  37. "cip": "1"
  38. }
  39. ]

        需要注意的是,这里面添加了"$type"字段,这是为了在反序列化是能得到正确类型的对象。

        最后需要说的是,在序列化和反序列化时应该使用相同的JsonSerializerSettings对象设置。于是我写了一个类来简化使用NewtonJson的代码,参考如下:

  1. using Newtonsoft.Json;
  2. public class JsonTool
  3. {
  4. static JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, ReferenceLoopHandling = ReferenceLoopHandling.Ignore};
  5. public static string ToJson(object obj) { return JsonConvert.SerializeObject(obj, settings);}
  6. public static T FromJson<T>(string json) { return JsonConvert.DeserializeObject<T>(json, settings); }
  7. }

        现在,我们使用JsonTool.ToJson和JsonTool.FromJson就可以了。

        如果你之前使用的是Unity内置的JsonUtility,现在直接用JsonTool搜索并替换JsonUtility就可以了。

//----------------------------------------------------------------------------------------------------------------------------

        好吧,其实还是有问题。

        本来以为万事大吉了,结果发现NewtonJson有个很神奇的错误,如果我给一个Color变量赋值,如果里面的rgba值为0或者为1就没有问题,如果是0到1之间的浮点数,Unity就直接退出,出这个问题的时候一直以为是别的方面的错误,最后一行代码一行代码的测试,才发现居然是NewtonJson的问题,最后想了个别的办法,所有用于序列化的类里面的Color都改成自定义的Vector4D,这样就不会出错,只不过要重载一大堆运算符,尤其是Vector4D,既要重载Vector4D和Vector4之间的操作,又要重载Vector4D和Color之间的操作,本来还想重载Vector4D和Quaternion之间的操作,感觉不大可能序列化Quaternion方面的东西,算了。

        当时序列化的时候还发现一个问题,就是序列化Vector3的时候会把Vector3对象的magnitude和sqrMagnitude的值也序列化了,这个是没有必要的,所以干脆在用于序列化的类里面把Vector3用Vector3D替代,把Vector2用Vector2D替代,这样序列化出来的内容就简洁而且不报错了。就是上面代码中的那行

settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

可以不用写了。
 

所定义的Vector2D、Vector3D、Vector4D参考如下:

  1. using System;
  2. using UnityEngine;
  3. [Serializable]
  4. public class TranP
  5. {
  6. public Vector3D position = Vector3.zero;
  7. public TranP(Vector3 position)
  8. {
  9. this.position = position;
  10. }
  11. public TranP() { position = Vector3.zero; }
  12. }
  13. [Serializable]
  14. public class TranPR : TranP
  15. {
  16. public Vector3D euler = Vector3.zero;
  17. public TranPR(Vector3 position, Vector3 euler) : base(position)
  18. {
  19. this.euler = euler;
  20. }
  21. public TranPR() : base() { euler = Vector3.zero; }
  22. public Quaternion GetRotation() { return Quaternion.Euler(euler); }
  23. }
  24. [Serializable]
  25. public class TranPRS : TranPR
  26. {
  27. public Vector3D scale = Vector3.one;
  28. public TranPRS(Vector3 position, Vector3 euler, Vector3 scale) : base(position, euler)
  29. {
  30. this.scale = scale;
  31. }
  32. public TranPRS() : base() { scale = Vector3.one; }
  33. }
  34. [Serializable]
  35. public class TranNP : TranP
  36. {
  37. public string name;
  38. public TranNP(string name, Vector3 position) : base(position)
  39. {
  40. this.name = name;
  41. }
  42. }
  43. [Serializable]
  44. public class TranNPR : TranPR
  45. {
  46. public string name;
  47. public TranNPR(string name, Vector3 position, Vector3 euler) : base(position, euler)
  48. {
  49. this.name = name;
  50. }
  51. }
  52. [Serializable]
  53. public class TranNPRS : TranPRS
  54. {
  55. public string name;
  56. public TranNPRS(string name, Vector3 position, Vector3 euler, Vector3 scale) : base(position, euler, scale)
  57. {
  58. this.name = name;
  59. }
  60. }
  61. [Serializable]
  62. public class CamRot
  63. {
  64. public float rotH;
  65. public float rotV;
  66. public CamRot(float rotH, float rotV) { this.rotH = rotH; this.rotV = rotV; }
  67. }
  68. [Serializable]
  69. public class TranCam
  70. {
  71. public Vector3D position;
  72. public CamRot camRot;
  73. public TranCam(Vector3 position, CamRot camRot)
  74. {
  75. this.position = position;
  76. this.camRot = camRot;
  77. }
  78. }
  79. [Serializable]
  80. public class Vector2D
  81. {
  82. public float x;
  83. public float y;
  84. public Vector2D()
  85. {
  86. x = 0;
  87. y = 0;
  88. }
  89. public Vector2D(float x, float y)
  90. {
  91. this.x = x;
  92. this.y = y;
  93. }
  94. public float GetSqrtMagnitude()
  95. {
  96. return x * x + y * y;
  97. }
  98. public float GetMagnitude()
  99. {
  100. return Mathf.Sqrt(GetSqrtMagnitude());
  101. }
  102. public static implicit operator Vector2D(Vector2 v)
  103. {
  104. return new Vector2D(v.x, v.y);
  105. }
  106. public static implicit operator Vector2(Vector2D v)
  107. {
  108. return new Vector2(v.x, v.y);
  109. }
  110. public static Vector2D operator +(Vector2D v1, Vector2D v2)
  111. {
  112. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  113. }
  114. public static Vector2D operator -(Vector2D v1, Vector2D v2)
  115. {
  116. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  117. }
  118. public static Vector2D operator *(Vector2D v, float f)
  119. {
  120. return new Vector2D(v.x * f, v.y * f);
  121. }
  122. public static Vector2D operator /(Vector2D v, float f)
  123. {
  124. return new Vector2D(v.x / f, v.y / f);
  125. }
  126. public static Vector2D operator +(Vector2D v1, Vector2 v2)
  127. {
  128. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  129. }
  130. public static Vector2D operator -(Vector2D v1, Vector2 v2)
  131. {
  132. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  133. }
  134. public static Vector2D operator +(Vector2 v1, Vector2D v2)
  135. {
  136. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  137. }
  138. public static Vector2D operator -(Vector2 v1, Vector2D v2)
  139. {
  140. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  141. }
  142. }
  143. [Serializable]
  144. public class Vector3D
  145. {
  146. public float x;
  147. public float y;
  148. public float z;
  149. public Vector3D()
  150. {
  151. x = 0;
  152. y = 0;
  153. z = 0;
  154. }
  155. public Vector3D(float x, float y, float z)
  156. {
  157. this.x = x;
  158. this.y = y;
  159. this.z = z;
  160. }
  161. public float GetSqrtMagnitude()
  162. {
  163. return x * x + y * y + z * z;
  164. }
  165. public float GetMagnitude()
  166. {
  167. return Mathf.Sqrt(GetSqrtMagnitude());
  168. }
  169. public static implicit operator Vector3D(Vector3 v)
  170. {
  171. return new Vector3D(v.x, v.y, v.z);
  172. }
  173. public static implicit operator Vector3(Vector3D v)
  174. {
  175. return new Vector3(v.x, v.y, v.z);
  176. }
  177. public static Vector3D operator +(Vector3D v1, Vector3D v2)
  178. {
  179. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  180. }
  181. public static Vector3D operator -(Vector3D v1, Vector3D v2)
  182. {
  183. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  184. }
  185. public static Vector3D operator *(Vector3D v, float f)
  186. {
  187. return new Vector3D(v.x * f, v.y * f, v.z * f);
  188. }
  189. public static Vector3D operator /(Vector3D v, float f)
  190. {
  191. return new Vector3D(v.x / f, v.y / f, v.z / f);
  192. }
  193. public static Vector3D operator +(Vector3D v1, Vector3 v2)
  194. {
  195. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  196. }
  197. public static Vector3D operator -(Vector3D v1, Vector3 v2)
  198. {
  199. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  200. }
  201. public static Vector3D operator +(Vector3 v1, Vector3D v2)
  202. {
  203. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  204. }
  205. public static Vector3D operator -(Vector3 v1, Vector3D v2)
  206. {
  207. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  208. }
  209. }
  210. [Serializable]
  211. public class Vector4D
  212. {
  213. public float r;
  214. public float g;
  215. public float b;
  216. public float a;
  217. public Vector4D() { r = 1; g = 1; b = 1; a = 1; }
  218. public Vector4D(float r, float g, float b, float a)
  219. {
  220. this.r = r;
  221. this.g = g;
  222. this.b = b;
  223. this.a = a;
  224. }
  225. public static implicit operator Vector4D(Color c)
  226. {
  227. return new Vector4D(c.r, c.g, c.b, c.a);
  228. }
  229. public static implicit operator Color(Vector4D c)
  230. {
  231. return new Color(c.r, c.g, c.b, c.a);
  232. }
  233. public static Vector4D operator +(Vector4D v1, Vector4D v2)
  234. {
  235. return new Vector4D(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
  236. }
  237. public static Vector4D operator -(Vector4D v1, Vector4D v2)
  238. {
  239. return new Vector4D(v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
  240. }
  241. public static Vector4D operator *(Vector4D v, float f)
  242. {
  243. return new Vector4D(v.r * f, v.g * f, v.b * f, v.a * f);
  244. }
  245. public static Vector4D operator /(Vector4D v, float f)
  246. {
  247. return new Vector4D(v.r / f, v.g / f, v.b / f, v.a / f);
  248. }
  249. public static Vector4D operator +(Vector4D v1, Vector4 v2)
  250. {
  251. return new Vector4D(v1.r + v2.x, v1.g + v2.y, v1.b + v2.z, v1.a + v2.w);
  252. }
  253. public static Vector4D operator -(Vector4D v1, Vector4 v2)
  254. {
  255. return new Vector4D(v1.r - v2.x, v1.g - v2.y, v1.b - v2.z, v1.a - v2.w);
  256. }
  257. public static Vector4D operator +(Vector4 v1, Vector4D v2)
  258. {
  259. return new Vector4D(v1.x + v2.r, v1.y + v2.g, v1.z + v2.b, v1.w + v2.a);
  260. }
  261. public static Vector4D operator -(Vector4 v1, Vector4D v2)
  262. {
  263. return new Vector4D(v1.x - v2.r, v1.y - v2.g, v1.z - v2.b, v1.w - v2.a);
  264. }
  265. }

        希望这次没有问题了吧。

//----------------------------------------------------------------------------------------------------------------------------

        不是的,还有一些小问题,代码里面有些地方用的是Vector3的magnitude,但是Vector3D里面没有,关键是我不能加这个属性啊,一加这个属性,序列化又多出magnitude和sqrtMagnitude这个内容了,所以如果需要的化,就添加一个GetMagnitude()方法和GetSqrtMagnitude()方法替代,或者用Vector3.Distance方法解决吧,有些地方需要Quaternion对象作为返回属性的就写个GetQuaternion()方法替代吧。

        希望没问题了,呵呵。

//----------------------------------------------------------------------------------------------------------------------------

        好吧,我又幼稚了,原来的Vector3是struct,但是现在定义的Vector3D之类的都是class,由于class允许设置位null,但是struct不行,所以如果当Vector3D的对象为null的时候,如果赋值给一个Vector3对象,会出现莫名奇妙的运行错误,并且不提示!比如说for循环或者foreach循环执行到这个赋值的位置直接跳出去!疯了!!疯了!!!

        后来查看了一下相关代码,应该是这样的,当class的对象为null赋值给一个struct时,就会导致执行错误,比如说莫名其妙的跳出循环,因为struct不可能是null啊,关键是不报错,后面的还能正常执行,也是醉了。

        所以最终的代码应该是把class都换成struct,就像下面这样的:

  1. [Serializable]
  2. public struct Vector2D
  3. {
  4. public float x;
  5. public float y;
  6. public Vector2D(float x, float y)
  7. {
  8. this.x = x;
  9. this.y = y;
  10. }
  11. public readonly float GetSqrtMagnitude()
  12. {
  13. return x * x + y * y;
  14. }
  15. public readonly float GetMagnitude()
  16. {
  17. return Mathf.Sqrt(GetSqrtMagnitude());
  18. }
  19. public static implicit operator Vector2D(Vector2 v)
  20. {
  21. return new Vector2D(v.x, v.y);
  22. }
  23. public static implicit operator Vector2(Vector2D v)
  24. {
  25. return new Vector2(v.x, v.y);
  26. }
  27. public static Vector2D operator +(Vector2D v1, Vector2D v2)
  28. {
  29. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  30. }
  31. public static Vector2D operator -(Vector2D v1, Vector2D v2)
  32. {
  33. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  34. }
  35. public static Vector2D operator *(Vector2D v, float f)
  36. {
  37. return new Vector2D(v.x * f, v.y * f);
  38. }
  39. public static Vector2D operator /(Vector2D v, float f)
  40. {
  41. return new Vector2D(v.x / f, v.y / f);
  42. }
  43. public static Vector2D operator +(Vector2D v1, Vector2 v2)
  44. {
  45. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  46. }
  47. public static Vector2D operator -(Vector2D v1, Vector2 v2)
  48. {
  49. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  50. }
  51. public static Vector2D operator +(Vector2 v1, Vector2D v2)
  52. {
  53. return new Vector2D(v1.x + v2.x, v1.y + v2.y);
  54. }
  55. public static Vector2D operator -(Vector2 v1, Vector2D v2)
  56. {
  57. return new Vector2D(v1.x - v2.x, v1.y - v2.y);
  58. }
  59. }
  60. [Serializable]
  61. public struct Vector3D
  62. {
  63. public float x;
  64. public float y;
  65. public float z;
  66. public Vector3D(float x, float y, float z)
  67. {
  68. this.x = x;
  69. this.y = y;
  70. this.z = z;
  71. }
  72. public readonly float GetSqrtMagnitude()
  73. {
  74. return x * x + y * y + z * z;
  75. }
  76. public readonly float GetMagnitude()
  77. {
  78. return Mathf.Sqrt(GetSqrtMagnitude());
  79. }
  80. public static implicit operator Vector3D(Vector3 v)
  81. {
  82. return new Vector3D(v.x, v.y, v.z);
  83. }
  84. public static implicit operator Vector3(Vector3D v)
  85. {
  86. return new Vector3(v.x, v.y, v.z);
  87. }
  88. public static Vector3D operator +(Vector3D v1, Vector3D v2)
  89. {
  90. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  91. }
  92. public static Vector3D operator -(Vector3D v1, Vector3D v2)
  93. {
  94. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  95. }
  96. public static Vector3D operator *(Vector3D v, float f)
  97. {
  98. return new Vector3D(v.x * f, v.y * f, v.z * f);
  99. }
  100. public static Vector3D operator /(Vector3D v, float f)
  101. {
  102. return new Vector3D(v.x / f, v.y / f, v.z / f);
  103. }
  104. public static Vector3D operator +(Vector3D v1, Vector3 v2)
  105. {
  106. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  107. }
  108. public static Vector3D operator -(Vector3D v1, Vector3 v2)
  109. {
  110. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  111. }
  112. public static Vector3D operator +(Vector3 v1, Vector3D v2)
  113. {
  114. return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
  115. }
  116. public static Vector3D operator -(Vector3 v1, Vector3D v2)
  117. {
  118. return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
  119. }
  120. }
  121. [Serializable]
  122. public struct Vector4D
  123. {
  124. public float r;
  125. public float g;
  126. public float b;
  127. public float a;
  128. public Vector4D(float r, float g, float b, float a)
  129. {
  130. this.r = r;
  131. this.g = g;
  132. this.b = b;
  133. this.a = a;
  134. }
  135. public static implicit operator Vector4D(Color c)
  136. {
  137. return new Vector4D(c.r, c.g, c.b, c.a);
  138. }
  139. public static implicit operator Color(Vector4D c)
  140. {
  141. return new Color(c.r, c.g, c.b, c.a);
  142. }
  143. public static Vector4D operator +(Vector4D v1, Vector4D v2)
  144. {
  145. return new Vector4D(v1.r + v2.r, v1.g + v2.g, v1.b + v2.b, v1.a + v2.a);
  146. }
  147. public static Vector4D operator -(Vector4D v1, Vector4D v2)
  148. {
  149. return new Vector4D(v1.r - v2.r, v1.g - v2.g, v1.b - v2.b, v1.a - v2.a);
  150. }
  151. public static Vector4D operator *(Vector4D v, float f)
  152. {
  153. return new Vector4D(v.r * f, v.g * f, v.b * f, v.a * f);
  154. }
  155. public static Vector4D operator /(Vector4D v, float f)
  156. {
  157. return new Vector4D(v.r / f, v.g / f, v.b / f, v.a / f);
  158. }
  159. public static Vector4D operator +(Vector4D v1, Vector4 v2)
  160. {
  161. return new Vector4D(v1.r + v2.x, v1.g + v2.y, v1.b + v2.z, v1.a + v2.w);
  162. }
  163. public static Vector4D operator -(Vector4D v1, Vector4 v2)
  164. {
  165. return new Vector4D(v1.r - v2.x, v1.g - v2.y, v1.b - v2.z, v1.a - v2.w);
  166. }
  167. public static Vector4D operator +(Vector4 v1, Vector4D v2)
  168. {
  169. return new Vector4D(v1.x + v2.r, v1.y + v2.g, v1.z + v2.b, v1.w + v2.a);
  170. }
  171. public static Vector4D operator -(Vector4 v1, Vector4D v2)
  172. {
  173. return new Vector4D(v1.x - v2.r, v1.y - v2.g, v1.z - v2.b, v1.w - v2.a);
  174. }
  175. }

        哈哈,这绝对是最后一次修改!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/861806
推荐阅读
相关标签
  

闽ICP备14008679号