C#中如何实现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;
- }
在前面的文章中使用的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/46998695
https://blog.csdn.net/xuexiaodong009/article/details/47004105
C#中如何实现json转化时只处理部分属性的更多相关文章
- js对象转换为json格式时,js对象属性中有值为null和undefined注意事项
当属性值为null时: 当属性值为undefined时: 只有当属性值为未定义时, js对象转换成json格式时会忽略该属性.
- 在magento的eav模型中如何在更新记录时只在value表的原值上更新
1,一般情况下,当我们在调用getModel在load某条实体接着更新对应实体上的值是,都不会覆盖原来的实体value表上的值,而是保留原来的,并在value表上重新创建一条值记录,比如初始表如下: ...
- springmvc 后台实体类接受前端json字符串时,其中一个属性content 接受富文本内容时 标签<p>、<span> 这些标签丢失问题解决
问题描述: 前端一个字段 <script id="editor" type="text/plain" name="content" s ...
- 解决nodejs中json序列化时Date类型默认为UTC格式
在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 上面只是一个例子,下面我用一个更具体化的例子来展示一个这个情况,我们在开发WEB项目中,经常用到Express组件, 我 ...
- 解决nodejs中json序列化时Date类型为UTC格式
在nodejs中,json序列化时Date类型时,默认转为UTC格式. 如下图 zhupengfei@DESKTOP-HJASOE3 MINGW64 /d/MyProject/exp2 $ node ...
- 在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出MethodArgumentNotValidException异常,因此,只需要在ExceptionHandler类中添加处理对应异常的方法即可。
在SpringMVC中,当Json序列化,反序列化失败的时候,会抛出HttpMessageNotReadableException异常, 当Bean validation失败的时候,会抛出Method ...
- python中json序列化时汉字变成编码的解决方式
我们在使用json模块时,如果被序列化对象中不包含汉字,当然没有任何问题,但是有汉字会被编译成unicode码: import json dic = {","sex":& ...
- 1.4.1 对象与JSON转化 1.4.2 JSON与List集合转化 1.1.1 获取json中的属性 day10-05
1.1.1 对象与JSON转化 @Test public void toJSON() throws IOException{ Jedis jedis = new Jedis("192.168 ...
- [转]javascript eval函数解析json数据时为什加上圆括号eval("("+data+")")
javascript eval函数解析json数据时为什么 加上圆括号?为什么要 eval这里要添加 “("("+data+")");//”呢? 原因在于: ...
随机推荐
- 为什么不同网段的ip 不能直接通信
首先要明白一点,IOS一共七层, 发送数据的过程是从上到下,也就是从应用层一直到物理层,接受数据是从下至上. 来看你的问题,环境如下,我们来用一个ping命令的过程来解释:一个交换机,连两个电脑A和B ...
- 20165326 java实验一
<Java程序设计>Java开发环境的熟悉 实验报告 课程:Java程序设计 班级:1653班 姓名:陈卓 学号:20165326 指导教师:娄嘉鹏 实验日期:2018年4月2日 实验时间 ...
- Git客户端的安装与配置入门
GitLab与Git客户端的安装与配置入门,每次配置完一段时间,就忘记配置过程了,为了自己和同学们以后有所参照,特记录了本次下载和配置,其实Git就是一个版本控制系统,类似于SVN,CVS等 下载:W ...
- js 自执行匿名函数(转载)
自执行匿名函数: 常见格式:(function() { /* code */ })(); 解释:包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命 ...
- ios初识UITableView及简单用法二(模型数据)
// // ViewController.m // ZQRTableViewTest // // Created by zzqqrr on 17/8/24. // Copyright (c) 2017 ...
- python基础举例应用
将下述两个变量的值交换s1='alex's2='SB's1,s2=s2,s1print(s1,s2) 判断下述结果msg1='alex say my name is alex,my age is 73 ...
- 用StringHelper.Split分解字符串
StringHelper提供了大量的方法,从而用链试写法处理字符串,实现对字符串的各种操作.比如: var s1,s2:string; begin s1:='abcdefg'; s2:=s1.subs ...
- 《统计学习方法》笔记(9):EM算法和隐马尔科夫模型
EM也称期望极大算法(Expectation Maximization),是一种用来对含有隐含变量的概率模型进行极大似然估计的迭代算法.该算法可应用于隐马尔科夫模型的参数估计. 1.含有隐含参数的概率 ...
- Java虚拟机的组成
Java虚拟机主要分为以下五个区: 一.方法区: 1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区里的常量池和对类型的卸载 2. 方法区主要用 ...
- HDU 1796 How many integers can you find(容斥原理)
题目传送:http://acm.hdu.edu.cn/diy/contest_showproblem.php?cid=20918&pid=1002 Problem Description ...