CustomJson.cs 6.7 KB

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