CustomJson.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. Type type = o.GetType();
  85. Func<object, JToken> importer = null;
  86. importerDict.TryGetValue(type, out importer);
  87. if (importer == null) {
  88. if (IsArray(type) && type.GetArrayRank() == 1) { //是一维数组才会触发
  89. Type elemType = type.GetElementType();
  90. importerDict.TryGetValue(elemType, out importer);
  91. if (importer == null) throw new Exception($"缺少Type<{elemType.Name}>的Importer");
  92. JArray ja = new JArray();
  93. Array arr = (Array) o;
  94. for (int i = 0; i < arr.Length; i++) ja.Add(importer.Invoke(arr.GetValue(i)));
  95. return ja;
  96. } else {
  97. throw new Exception($"缺少Type<{type.Name}>的Importer");
  98. }
  99. }
  100. return importer.Invoke(o);
  101. }
  102. public T ParseByExporter<T>(JToken jt)
  103. {
  104. return (T)ParseByExporter(jt, typeof(T));
  105. }
  106. public object ParseByExporter(JToken jt, Type type)
  107. {
  108. Func<JToken, object> exporter = null;
  109. exporterDict.TryGetValue(type, out exporter);
  110. if (exporter == null) {
  111. if (IsArray(type) && type.GetArrayRank() == 1) { //是一维数组才会触发
  112. Type elemType = type.GetElementType();
  113. exporterDict.TryGetValue(elemType, out exporter);
  114. if (exporter == null) throw new Exception($"缺少Type<{elemType.Name}>的Exporter");
  115. var ja = (JArray) jt;
  116. var arr = Array.CreateInstance(elemType, ja.Count);
  117. for (int i = 0; i < arr.Length; i++) arr.SetValue(exporter.Invoke(ja[i]), i);
  118. return arr;
  119. } else {
  120. throw new Exception($"缺少Type<{type.Name}>的Exporter");
  121. }
  122. }
  123. return exporter.Invoke(jt);
  124. }
  125. public void FetchFieldValues(object target, JToken fromJson, params string[] fieldNames) {
  126. Type targetType = target.GetType();
  127. foreach (var fieldName in fieldNames)
  128. {
  129. FieldInfo targetField = targetType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  130. if (targetField == null) {
  131. PropertyInfo propertyInfo = targetType.GetProperty(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  132. if (propertyInfo == null) {
  133. throw new Exception($"获取PropertyInfo[{fieldName}]失败");
  134. } else {
  135. object fieldValue = ParseByExporter(fromJson[fieldName], propertyInfo.PropertyType);
  136. propertyInfo.SetValue(target, fieldValue);
  137. }
  138. } else {
  139. object fieldValue = ParseByExporter(fromJson[fieldName], targetField.FieldType);
  140. targetField.SetValue(target, fieldValue);
  141. }
  142. }
  143. }
  144. public bool IsArray(Type type)
  145. {
  146. return type.BaseType == typeof(Array);
  147. }
  148. }
  149. }