C#中如何实现json转化时只处理部分属性
.net中如何实现json转化时只处理部分属性一
把对象转化为json字符串,很常用,但如果因为现在大部分项目都是用了ORM映射,导致一个对象的属性特别多,如果前台只需要部分属性如何实现?
当然最简单是所有属性都json化,前台只处理需要的属性,多余的不管。那有没有一种方式可以实现,对于同一种类型,按照前台的需要只处理json需要的属性呢?
在.Net中把对象转为json字符串主要有四种,具体参考
1自己转化灵活,但难度大,能实现。
2使用Newtonsoft.Json,看了一下官方文档,似乎不能实现,能忽略默认,空值等属性,也可以控制json时输出那些属性,但需要使用特性,也就是说,对于指定的类型,json输出的属性是确定的,不能动态改变。
3使用JavaScriptSerializer类,查看了官方文档,没找到方法,不能实现
4也是使用的是特性,没找到方法,不能实现。
没有现成的方法,也就只能自己实现了。我们知道把对象转化为json字符串,核心自然是使用反射得到需要的属性和属性的值。但如果属性是一个类对象呢?,数组或者是泛型呢?
另外如果字符串中包含特殊字符如何处理?
于是自己也就实现了一个简单的
/// <summary> /// 把对象转化为json字符串 /// </summary> /// <typeparam name="T">需要转化的对象的类型</typeparam> /// <param name="t">需要转化的对象</param> /// <param name="propertyInfos">需要转换的字段列表,用逗号分隔</param> /// <returns></returns> public static string ConvertFromModeTojson<T>(T t, string propertyInfos) where T : class { string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); System.Text.StringBuilder sb = new System.Text.StringBuilder(300); string result = "{"; foreach (string col in cols) { string str = GetOneProperty<T>(t, col); sb.Append(str); } result += sb.ToString().TrimEnd(','); result += "}"; return result; } private static string GetOneProperty<T>(T t, string pname) where T : class { Type type = t.GetType(); PropertyInfo pinfo = type.GetProperty(pname);//使用反射获得属性 if (pinfo != null) { object v = pinfo.GetValue(t, null);//使用反射获得属性的值 string tt = PropertyTypeValue(pinfo.PropertyType, v, pname); return tt; } else { throw new Exception("不存在属性" + pname); } } /// <summary> /// 按照数字格式输入的类型 /// </summary> private static readonly List<Type> TypeNumCodeList = new List<Type>{ { typeof(sbyte)}, { typeof(sbyte?)}, { typeof(short)}, { typeof(short?)}, { typeof(ushort)}, { typeof(ushort?)}, { typeof(int)}, { typeof(int?)}, { typeof(byte)}, { typeof(byte?)}, { typeof(uint)}, { typeof(uint?)}, { typeof(long)}, { typeof(long?)}, { typeof(ulong)}, { typeof(ulong?)}, { typeof(float)}, { typeof(float?)}, { typeof(double) }, { typeof(double?)}, { typeof(decimal)}, { typeof(decimal?)}, { typeof(bool)}, { typeof(bool?)} }; /// <summary> /// 按照文字格式输入的类型 /// </summary> private static readonly List<Type> TypeStrCodeList = new List<Type>{ { typeof(char)}, { typeof(char?)}, { typeof(DateTime)}, { typeof(DateTime?)} }; /// <summary> /// 根据字段类型进行罗列,显然不能处理所有的类型,也没有处理字段是数组,对象的情况 /// </summary> /// <param name="propertytype"></param> /// <param name="value"></param> /// <param name="propertyName"></param> /// <returns></returns> private static string PropertyTypeValue(Type propertytype, object value, string propertyName) { string valueStr = value != null ? value.ToString() : ""; string returnStr = ""; if (TypeNumCodeList.Contains(propertytype)) { if (!string.IsNullOrEmpty(valueStr))//忽略掉空值 { returnStr = string.Format("\"{0}\":{1},", propertyName, valueStr); } } else if (TypeStrCodeList.Contains(propertytype)) { if (!string.IsNullOrEmpty(valueStr))//忽略掉空值 { returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, valueStr); } } else if (propertytype == typeof(string)) { if (!string.IsNullOrEmpty(valueStr))//忽略掉空值,并处理字符串中的特殊字符 { returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, String2Json(valueStr)); } } else //对象,数组等不能处理, { returnStr = string.Format("\"{0}\":\"{1}\",", propertyName, String2Json(valueStr)); } return returnStr; } /// <summary> /// 过滤特殊字符 /// </summary> /// <param name="s"></param> /// <returns></returns> private static string String2Json(string s) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.Length; i++) { char c = s.ToCharArray()[i]; switch (c) { case '\"': sb.Append("\\\""); break; case '\\': sb.Append("\\\\"); break; case '/': sb.Append("\\/"); break; case '\b': sb.Append("\\b"); break; case '\f': sb.Append("\\f"); break; case '\n': sb.Append("\\n"); break; case '\r': sb.Append("\\r"); break; case '\t': sb.Append("\\t"); break; /* case '<': sb.Append("<"); break; case '>': sb.Append(">"); break;*/ default: if ((c >= 0 && c <= 31) || c == 127)//在ASCⅡ码中,第0~31号及第127号(共33个)是控制字符或通讯专用字符 { } else { sb.Append(c); } break; } } return sb.ToString(); }
很显然,这个实现有很大的问题,字符串中包含的特殊字符不一定处理完了,泛型,数组等属性都没有处理,但是简单对象还是可以处理的。
既然Newtonsoft.Json是开源的,那能不能利用它实现呢?
于是使用Newtonsoft.Json改进了以上代码
private static readonly List<Type> TypeCodeList = new List<Type>{ { typeof(char)}, { typeof(char?)}, { typeof(bool)}, { typeof(bool?)}, { typeof(sbyte)}, { typeof(sbyte?)}, { typeof(short)}, { typeof(short?)}, { typeof(ushort)}, { typeof(ushort?)}, { typeof(int)}, { typeof(int?)}, { typeof(byte)}, { typeof(byte?)}, { typeof(uint)}, { typeof(uint?)}, { typeof(long)}, { typeof(long?)}, { typeof(ulong)}, { typeof(ulong?)}, { typeof(float)}, { typeof(float?)}, { typeof(double) }, { typeof(double?)}, { typeof(DateTime)}, { typeof(DateTime?)}, { typeof(DateTimeOffset)}, { typeof(DateTimeOffset?)}, { typeof(decimal)}, { typeof(decimal?)}, { typeof(Guid)}, { typeof(Guid?)}, { typeof(TimeSpan)}, { typeof(TimeSpan?)}, { typeof(Uri)}, { typeof(string)}, { typeof(byte[])}, { typeof(DBNull)} }; /// <summary> /// 把对象转化为json字符串,依然不能处理属性是泛型,数组,对象等类型 /// </summary> /// <typeparam name="T">需要转化的对象的类型</typeparam> /// <param name="t">需要转化的对象</param> /// <param name="propertyInfos">需要转换的字段列表,用逗号分隔</param> /// <returns></returns> public static string ConvertFromModeTojson<T>(T t, string propertyInfos) where T : class { StringWriter sw = new StringWriter(); using (JsonTextWriter writer = new JsonTextWriter(sw)) { writer.WriteStartObject(); string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); foreach (string col in cols) { Type type = t.GetType(); PropertyInfo pinfo = type.GetProperty(col);//使用反射获得属性 if (pinfo != null) { object v = pinfo.GetValue(t, null);//使用反射获得属性的值 Type pinfoType = pinfo.PropertyType; if (TypeCodeList.Contains(pinfoType)) { writer.WritePropertyName(col); writer.WriteValue(v); } else { //其他类型的忽略,避免异常 } } else { throw new Exception("不存在属性" + col); } } writer.WriteEndObject(); writer.Flush(); } string jsonText = sw.GetStringBuilder().ToString(); return jsonText; }
出处:https://blog.csdn.net/xuexiaodong009/article/details/46998695
=======================================================================================
.net中如何实现json转化时只处理部分属性二
在第一篇文章中使用的json方法,可以按照需要只处理需要的属性,但却要求属性不能是复杂的类型,例如泛型,数组,其他用户自定义的类等,限制太多,于是自己看看能不能改进,想不到Newtonsoft.Json提供有相关的接口,只需要实现就可以了。只需要继承DefaultContractResolver,并改写一个方法就可以了。
核心代码:
/// <summary> /// 对象转为json,所有属性都输出 /// </summary> /// <typeparam name="ObjType"></typeparam> /// <param name="obj"></param> /// <returns></returns> public static string ObjToJsonString<ObjType>(ObjType obj) where ObjType : class { string s = JsonConvert.SerializeObject(obj); return s; } /// <summary> /// 对象转为json,只输出部分属性 /// </summary> /// <typeparam name="T">对象类型</typeparam> /// <param name="t">对象类型值</param> /// <param name="propertyInfos">需要json处理的属性名称,以逗号分隔</param> /// <returns></returns> public static string ObjToJsonString<T>(T t, string propertyInfos) where T : class { string[] cols = propertyInfos.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); List<string> _propertyNames = new List<string>(); foreach (string col in cols) { string colTemp = col.ToLower().Trim(); if (!_propertyNames.Contains(colTemp)) { _propertyNames.Add(colTemp); } } string s = JsonConvert.SerializeObject(t, Formatting.Indented, new JsonSerializerSettings { ContractResolver = new DynamicContractResolver(_propertyNames) }); return s; } /// <summary> /// json转为对象 /// </summary> /// <typeparam name="ObjType"></typeparam> /// <param name="JsonString"></param> /// <returns></returns> public static ObjType JsonStringToObj<ObjType>(string JsonString) where ObjType : class { ObjType s = JsonConvert.DeserializeObject<ObjType>(JsonString); return s; } class DynamicContractResolver : DefaultContractResolver { private readonly List<string> _propertyNames; public DynamicContractResolver(List<string> propertyNames) { _propertyNames = propertyNames; } /// <summary> /// 如果属性是对象,需要把这个对象的属性也传给propertyNames, /// 否则处理这个对象属性时,就不包含对应的属性值 /// </summary> /// <param name="type"></param> /// <param name="memberSerialization"></param> /// <returns></returns> protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization); IList<JsonProperty> propertiesReturn = new List<JsonProperty>();//需要json处理的属性 foreach (JsonProperty item in properties) { string PropertyNameTemp = item.PropertyName.ToLower().Trim(); if (_propertyNames.Contains(PropertyNameTemp)) { propertiesReturn.Add(item); } } return propertiesReturn; } }
出处:https://blog.csdn.net/xuexiaodong009/article/details/47004105
=======================================================================================
个人使用
我参考上面的说法,以及参考:C#中 Newtonsoft.Json 高级用法 =>7.动态决定属性是否序列化 的对应章节内容,设计和优化代码如下:
优化一
namespace ConsoleApp1.Comm { using Newtonsoft.Json; using Newtonsoft.Json.Serialization; /// <summary> /// 限制属性序列化或反序列化转换器 /// </summary> public class LimitPropertysContractResolver : DefaultContractResolver { /// <summary> /// 序列化或反序列化时,指定属性是包含,还是忽略 /// </summary> public enum PropertyOutType { Include = 0, Ignore } string[] propsArr = null; PropertyOutType propsOutType; /// <summary> /// 构造函数 /// </summary> /// <param name="propertysArray">传入的属性数组</param> /// <param name="propertyIgnore">表示propertysArray是要排除的字段,还是需要保留的字段,默认忽略</param> public LimitPropertysContractResolver(string[] propertysArray, PropertyOutType propertyOutType = PropertyOutType.Ignore) { //指定要序列化属性的清单 this.propsArr = propertysArray; this.propsOutType = propertyOutType; } protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); //只保留清单有列出的属性 return list.Where(p => { return propsOutType == PropertyOutType.Include ? propsArr.Contains(p.PropertyName) : !propsArr.Contains(p.PropertyName); }).ToList(); } } }
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/9411488.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2018-08-03 09:04 jack_Meng 阅读(4690) 评论(1) 编辑 收藏 举报