CustomJson.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using System;
  2. using System.Reflection;
  3. using System.Collections.Generic;
  4. using Newtonsoft.Json;
  5. using Newtonsoft.Json.Linq;
  6. namespace JCUnityLib
  7. {
  8. public class CustomJson
  9. {
  10. public Dictionary<Type, Func<object, JToken>> importerDict = new Dictionary<Type, Func<object, JToken>>();
  11. public Dictionary<Type, Func<JToken, object>> exporterDict = new Dictionary<Type, Func<JToken, object>>();
  12. public CustomJson()
  13. {
  14. //add importer
  15. importerDict.Add(typeof(short), (o) => JValue.FromObject(o));
  16. importerDict.Add(typeof(int), (o) => JValue.FromObject(o));
  17. importerDict.Add(typeof(long), (o) => JValue.FromObject(o));
  18. importerDict.Add(typeof(float), (o) => JValue.FromObject(o));
  19. importerDict.Add(typeof(double), (o) => JValue.FromObject(o));
  20. importerDict.Add(typeof(bool), (o) => JValue.FromObject(o));
  21. importerDict.Add(typeof(double[][]), (o) => JArray.FromObject(o));
  22. importerDict.Add(typeof(Nullable<bool>), (o) => JValue.FromObject(o));
  23. //add exporter
  24. exporterDict.Add(typeof(short), (jt) => jt.ToObject<short>());
  25. exporterDict.Add(typeof(int), (jt) => jt.ToObject<int>());
  26. exporterDict.Add(typeof(long), (jt) => jt.ToObject<long>());
  27. exporterDict.Add(typeof(float), (jt) => jt.ToObject<float>());
  28. exporterDict.Add(typeof(double), (jt) => jt.ToObject<double>());
  29. exporterDict.Add(typeof(bool), (jt) => jt.ToObject<bool>());
  30. exporterDict.Add(typeof(double[][]), (jt) => ((JArray)jt).ToObject<double[][]>());
  31. exporterDict.Add(typeof(Nullable<bool>), (jt) => jt.ToObject<Nullable<bool>>());
  32. }
  33. public void InitJsonClass<T>(Func<object, JToken> importer, Func<JToken, object> exporter)
  34. {
  35. Type type = typeof(T);
  36. importerDict.Add(type, importer);
  37. exporterDict.Add(type, exporter);
  38. }
  39. public void InitJsonClass<T>(Func<object> ctor, params string[] props)
  40. {
  41. Type type = typeof(T);
  42. exporterDict.Add(type, (jt) => {
  43. var o = ctor.Invoke();
  44. FetchFieldValues(o, jt, props);
  45. return o;
  46. });
  47. importerDict.Add(type, (o) => {
  48. JToken jt = new JObject();
  49. FetchJsonProperties(jt, o, props);
  50. return jt;
  51. });
  52. }
  53. public T Parse<T>(string text)
  54. {
  55. var jt = JToken.Parse(text);
  56. return (T)ParseByExporter(jt, typeof(T));
  57. }
  58. public string Stringify(object o)
  59. {
  60. return JsonConvert.SerializeObject(ToJTokenByImporter(o));
  61. }
  62. public void FetchJsonProperties(JToken target, object fromObject, params string[] propertyNames)
  63. {
  64. Type fromObjectType = fromObject.GetType();
  65. foreach (var propertyName in propertyNames)
  66. {
  67. FieldInfo targetField = fromObjectType.GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  68. if (targetField == null) {
  69. PropertyInfo propertyInfo = fromObjectType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  70. if (propertyInfo == null) {
  71. throw new Exception($"获取PropertyInfo[{propertyName}]失败");
  72. } else {
  73. JToken propertyValue = ToJTokenByImporter(propertyInfo.GetValue(fromObject));
  74. target[propertyName] = propertyValue;
  75. }
  76. } else {
  77. JToken propertyValue = ToJTokenByImporter(targetField.GetValue(fromObject));
  78. target[propertyName] = propertyValue;
  79. }
  80. }
  81. }
  82. public JToken ToJTokenByImporter(object o)
  83. {
  84. if (o == null) return null;
  85. Type type = o.GetType();
  86. Func<object, JToken> importer = null;
  87. importerDict.TryGetValue(type, out importer);
  88. if (importer == null) {
  89. if (IsArray(type) && type.GetArrayRank() == 1) { //是一维数组才会触发
  90. Type elemType = type.GetElementType();
  91. importerDict.TryGetValue(elemType, out importer);
  92. if (importer == null) throw new Exception($"缺少Type<{elemType.Name}>的Importer");
  93. JArray ja = new JArray();
  94. Array arr = (Array) o;
  95. for (int i = 0; i < arr.Length; i++) ja.Add(importer.Invoke(arr.GetValue(i)));
  96. return ja;
  97. } else {
  98. throw new Exception($"缺少Type<{type.Name}>的Importer");
  99. }
  100. }
  101. return importer.Invoke(o);
  102. }
  103. public T ParseByExporter<T>(JToken jt)
  104. {
  105. return (T)ParseByExporter(jt, typeof(T));
  106. }
  107. public object ParseByExporter(JToken jt, Type type)
  108. {
  109. if (jt.Type == JTokenType.Null) return null;
  110. Func<JToken, object> exporter = null;
  111. exporterDict.TryGetValue(type, out exporter);
  112. if (exporter == null) {
  113. if (IsArray(type) && type.GetArrayRank() == 1) { //是一维数组才会触发
  114. Type elemType = type.GetElementType();
  115. exporterDict.TryGetValue(elemType, out exporter);
  116. if (exporter == null) throw new Exception($"缺少Type<{elemType.Name}>的Exporter");
  117. var ja = (JArray) jt;
  118. var arr = Array.CreateInstance(elemType, ja.Count);
  119. for (int i = 0; i < arr.Length; i++) arr.SetValue(exporter.Invoke(ja[i]), i);
  120. return arr;
  121. } else {
  122. throw new Exception($"缺少Type<{type.Name}>的Exporter");
  123. }
  124. }
  125. return exporter.Invoke(jt);
  126. }
  127. public void FetchFieldValues(object target, JToken fromJson, params string[] fieldNames) {
  128. Type targetType = target.GetType();
  129. foreach (var fieldName in fieldNames)
  130. {
  131. FieldInfo targetField = targetType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  132. if (targetField == null) {
  133. PropertyInfo propertyInfo = targetType.GetProperty(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  134. if (propertyInfo == null) {
  135. throw new Exception($"获取PropertyInfo[{fieldName}]失败");
  136. } else {
  137. object fieldValue = ParseByExporter(fromJson[fieldName], propertyInfo.PropertyType);
  138. propertyInfo.SetValue(target, fieldValue);
  139. }
  140. } else {
  141. object fieldValue = ParseByExporter(fromJson[fieldName], targetField.FieldType);
  142. targetField.SetValue(target, fieldValue);
  143. }
  144. }
  145. }
  146. public bool IsArray(Type type)
  147. {
  148. return type.BaseType == typeof(Array);
  149. }
  150. }
  151. }