C#中如何实现json转化时只处理部分属性

时间:2023-03-08 16:54:32
C#中如何实现json转化时只处理部分属性

把对象转化为json字符串,很常用,但如果因为现在大部分项目都是用了ORM映射,导致一个对象的属性特别多,如果前台只需要部分属性如何实现?

当然最简单是所有属性都json化,前台只处理需要的属性,多余的不管。那有没有一种方式可以实现,对于同一种类型,按照前台的需要只处理json需要的属性呢?

在.Net中把对象转为json字符串主要有四种方式:具体参考

1自己转化灵活,但难度大,能实现。

2使用Newtonsoft.Json,看了一下官方文档,似乎不能实现,能忽略默认,空值等属性,也可以控制json时输出那些属性,但需要使用特性,也就是说,对于指定的类型,json输出的属性是确定的,不能动态改变。

具体可参考

3使用JavaScriptSerializer类,查看了官方文档,没找到方法,不能实现

4也是使用的是特性,没找到方法,不能实现。

没有现成的方法,也就只能自己实现了。我们知道把对象转化为json字符串,核心自然是使用反射得到需要的属性和属性的值。但如果属性是一个类对象呢?,数组或者是泛型呢?

另外如果字符串中包含特殊字符如何处理?

于是自己也就实现了一个简单的

  1. /// <summary>
  2. /// 把对象转化为json字符串
  3. /// </summary>
  4. /// <typeparam name="T">需要转化的对象的类型</typeparam>
  5. /// <param name="t">需要转化的对象</param>
  6. /// <param name="propertyInfos">需要转换的字段列表,用逗号分隔</param>
  7. /// <returns></returns>
  8. public static string ConvertFromModeTojson<T>(T t, string propertyInfos) where T : class
  9. {
  10. string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  11. System.Text.StringBuilder sb = new System.Text.StringBuilder(300);
  12. string result = "{";
  13. foreach (string col in cols)
  14. {
  15. string str = GetOneProperty<T>(t, col);
  16. sb.Append(str);
  17. }
  18. result += sb.ToString().TrimEnd(',');
  19. result += "}";
  20. return result;
  21. }
  22. private static string GetOneProperty<T>(T t, string pname) where T : class
  23. {
  24. Type type = t.GetType();
  25. PropertyInfo pinfo = type.GetProperty(pname);//使用反射获得属性
  26. if (pinfo != null)
  27. {
  28. object v = pinfo.GetValue(t, null);//使用反射获得属性的值
  29. string tt = PropertyTypeValue(pinfo.PropertyType, v, pname);
  30. return tt;
  31. }
  32. else
  33. {
  34. throw new Exception("不存在属性" + pname);
  35. }
  36. }
  37. /// <summary>
  38. /// 按照数字格式输入的类型
  39. /// </summary>
  40. private static readonly List<Type> TypeNumCodeList = new List<Type>{
  41. { typeof(sbyte)},
  42. { typeof(sbyte?)},
  43. { typeof(short)},
  44. { typeof(short?)},
  45. { typeof(ushort)},
  46. { typeof(ushort?)},
  47. { typeof(int)},
  48. { typeof(int?)},
  49. { typeof(byte)},
  50. { typeof(byte?)},
  51. { typeof(uint)},
  52. { typeof(uint?)},
  53. { typeof(long)},
  54. { typeof(long?)},
  55. { typeof(ulong)},
  56. { typeof(ulong?)},
  57. { typeof(float)},
  58. { typeof(float?)},
  59. { typeof(double) },
  60. { typeof(double?)},
  61. { typeof(decimal)},
  62. { typeof(decimal?)},
  63. { typeof(bool)},
  64. { typeof(bool?)}
  65. };
  66. /// <summary>
  67. /// 按照文字格式输入的类型
  68. /// </summary>
  69. private static readonly List<Type> TypeStrCodeList = new List<Type>{
  70. { typeof(char)},
  71. { typeof(char?)},
  72. { typeof(DateTime)},
  73. { typeof(DateTime?)}
  74. };
  75. /// <summary>
  76. /// 根据字段类型进行罗列,显然不能处理所有的类型,也没有处理字段是数组,对象的情况
  77. /// </summary>
  78. /// <param name="propertytype"></param>
  79. /// <param name="value"></param>
  80. /// <param name="propertyName"></param>
  81. /// <returns></returns>
  82. private static string PropertyTypeValue(Type propertytype, object value, string propertyName)
  83. {
  84. string valueStr = value != null ? value.ToString() : "";
  85. string returnStr = "";
  86. if (TypeNumCodeList.Contains(propertytype))
  87. {
  88. if (!string.IsNullOrEmpty(valueStr))//忽略掉空值
  89. {
  90. returnStr = string.Format("\"{0}\":{1},", propertyName, valueStr);
  91. }
  92. }
  93. else if (TypeStrCodeList.Contains(propertytype))
  94. {
  95. if (!string.IsNullOrEmpty(valueStr))//忽略掉空值
  96. {
  97. returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, valueStr);
  98. }
  99. }
  100. else if (propertytype == typeof(string))
  101. {
  102. if (!string.IsNullOrEmpty(valueStr))//忽略掉空值,并处理字符串中的特殊字符
  103. {
  104. returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, String2Json(valueStr));
  105. }
  106. }
  107. else //对象,数组等不能处理,
  108. {
  109. returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, String2Json(valueStr));
  110. }
  111. return returnStr;
  112. }
  113. /// <summary>
  114. /// 过滤特殊字符
  115. /// </summary>
  116. /// <param name="s"></param>
  117. /// <returns></returns>
  118. private static string String2Json(string s)
  119. {
  120. StringBuilder sb = new StringBuilder();
  121. for (int i = 0; i < s.Length; i++)
  122. {
  123. char c = s.ToCharArray()[i];
  124. switch (c)
  125. {
  126. case '\"':
  127. sb.Append("\\\""); break;
  128. case '\\':
  129. sb.Append("\\\\"); break;
  130. case '/':
  131. sb.Append("\\/"); break;
  132. case '\b':
  133. sb.Append("\\b"); break;
  134. case '\f':
  135. sb.Append("\\f"); break;
  136. case '\n':
  137. sb.Append("\\n"); break;
  138. case '\r':
  139. sb.Append("\\r"); break;
  140. case '\t':
  141. sb.Append("\\t"); break;
  142. /* case '<':
  143. sb.Append("<"); break;
  144. case '>':
  145. sb.Append(">"); break;*/
  146. default:
  147. if ((c >= 0 && c <= 31) || c == 127)//在ASCⅡ码中,第0~31号及第127号(共33个)是控制字符或通讯专用字符
  148. {
  149. }
  150. else
  151. {
  152. sb.Append(c);
  153. }
  154. break;
  155. }
  156. }
  157. return sb.ToString();
  158. }

很显然,这个实现有很大的问题,字符串中包含的特殊字符不一定处理完了,泛型,数组等属性都没有处理,但是简单对象还是可以处理的。

既然Newtonsoft.Json是开源的,那能不能利用它实现呢?

于是使用Newtonsoft.Json改进了以上代码

  1. private static readonly List<Type> TypeCodeList = new List<Type>{
  2. { typeof(char)},
  3. { typeof(char?)},
  4. { typeof(bool)},
  5. { typeof(bool?)},
  6. { typeof(sbyte)},
  7. { typeof(sbyte?)},
  8. { typeof(short)},
  9. { typeof(short?)},
  10. { typeof(ushort)},
  11. { typeof(ushort?)},
  12. { typeof(int)},
  13. { typeof(int?)},
  14. { typeof(byte)},
  15. { typeof(byte?)},
  16. { typeof(uint)},
  17. { typeof(uint?)},
  18. { typeof(long)},
  19. { typeof(long?)},
  20. { typeof(ulong)},
  21. { typeof(ulong?)},
  22. { typeof(float)},
  23. { typeof(float?)},
  24. { typeof(double) },
  25. { typeof(double?)},
  26. { typeof(DateTime)},
  27. { typeof(DateTime?)},
  28. { typeof(DateTimeOffset)},
  29. { typeof(DateTimeOffset?)},
  30. { typeof(decimal)},
  31. { typeof(decimal?)},
  32. { typeof(Guid)},
  33. { typeof(Guid?)},
  34. { typeof(TimeSpan)},
  35. { typeof(TimeSpan?)},
  36. { typeof(Uri)},
  37. { typeof(string)},
  38. { typeof(byte[])},
  39. { typeof(DBNull)}
  40. };
  41. /// <summary>
  42. /// 把对象转化为json字符串,依然不能处理属性是泛型,数组,对象等类型
  43. /// </summary>
  44. /// <typeparam name="T">需要转化的对象的类型</typeparam>
  45. /// <param name="t">需要转化的对象</param>
  46. /// <param name="propertyInfos">需要转换的字段列表,用逗号分隔</param>
  47. /// <returns></returns>
  48. public static string ConvertFromModeTojson<T>(T t, string propertyInfos) where T : class
  49. {
  50. StringWriter sw = new StringWriter();
  51. using (JsonTextWriter writer = new JsonTextWriter(sw))
  52. {
  53. writer.WriteStartObject();
  54. string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  55. foreach (string col in cols)
  56. {
  57. Type type = t.GetType();
  58. PropertyInfo pinfo = type.GetProperty(col);//使用反射获得属性
  59. if (pinfo != null)
  60. {
  61. object v = pinfo.GetValue(t, null);//使用反射获得属性的值
  62. Type pinfoType = pinfo.PropertyType;
  63. if (TypeCodeList.Contains(pinfoType))
  64. {
  65. writer.WritePropertyName(col);
  66. writer.WriteValue(v);
  67. }
  68. else
  69. { //其他类型的忽略,避免异常
  70. }
  71. }
  72. else
  73. {
  74. throw new Exception("不存在属性" + col);
  75. }
  76. }
  77. writer.WriteEndObject();
  78. writer.Flush();
  79. }
  80. string jsonText = sw.GetStringBuilder().ToString();
  81. return jsonText;
  82. }

在前面的文章中使用的json方法,可以按照需要只处理需要的属性,但却要求属性不能是复杂的类型,例如泛型,数组,其他用户自定义的类等,限制太多,于是自己看看能不能改进,想不到Newtonsoft.Json提供有相关的接口,只需要实现就可以了。只需要继承DefaultContractResolver,并改写一个方法就可以了。

核心代码:

  1. /// <summary>
  2. /// 对象转为json,所有属性都输出
  3. /// </summary>
  4. /// <typeparam name="ObjType"></typeparam>
  5. /// <param name="obj"></param>
  6. /// <returns></returns>
  7. public static string ObjToJsonString<ObjType>(ObjType obj) where ObjType : class
  8. {
  9. string s = JsonConvert.SerializeObject(obj);
  10. return s;
  11. }
  12. /// <summary>
  13. /// 对象转为json,只输出部分属性
  14. /// </summary>
  15. /// <typeparam name="T">对象类型</typeparam>
  16. /// <param name="t">对象类型值</param>
  17. /// <param name="propertyInfos">需要json处理的属性名称,以逗号分隔</param>
  18. /// <returns></returns>
  19. public static string ObjToJsonString<T>(T t, string propertyInfos) where T : class
  20. {
  21. string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  22. List<string> _propertyNames = new List<string>();
  23. foreach (string col in cols)
  24. {
  25.  string   colTemp = col.ToLower().Trim();
  26. if (!_propertyNames.Contains(colTemp))
  27. {
  28. _propertyNames.Add(colTemp);
  29. }
  30. }
  31. string s = JsonConvert.SerializeObject(t, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new DynamicContractResolver(_propertyNames) });
  32. return s;
  33. }
  34. /// <summary>
  35. /// json转为对象
  36. /// </summary>
  37. /// <typeparam name="ObjType"></typeparam>
  38. /// <param name="JsonString"></param>
  39. /// <returns></returns>
  40. public static ObjType JsonStringToObj<ObjType>(string JsonString) where ObjType : class
  41. {
  42. ObjType s = JsonConvert.DeserializeObject<ObjType>(JsonString);
  43. return s;
  44. }
  45. class DynamicContractResolver : DefaultContractResolver
  46. {
  47. private readonly List<string> _propertyNames;
  48. public DynamicContractResolver(List<string> propertyNames)
  49. {
  50. _propertyNames = propertyNames;
  51. }
  52. /// <summary>
  53. /// 如果属性是对象,需要把这个对象的属性也传给propertyNames,
  54. /// 否则处理这个对象属性时,就不包含对应的属性值
  55. /// </summary>
  56. /// <param name="type"></param>
  57. /// <param name="memberSerialization"></param>
  58. /// <returns></returns>
  59. protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  60. {
  61. IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
  62. IList<JsonProperty> propertiesReturn = new List<JsonProperty>();//需要json处理的属性
  63. foreach (JsonProperty item in properties)
  64. string PropertyNameTemp = item.PropertyName.ToLower().Trim();
  65. if (_propertyNames.Contains(PropertyNameTemp))
  66. {
  67. propertiesReturn.Add(item);
  68. }
  69. }
  70. return propertiesReturn;
  71. }
  72. }

出处:

https://blog.csdn.net/xuexiaodong009/article/details/46998695

https://blog.csdn.net/xuexiaodong009/article/details/47004105