把对象转化为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 '':
-
sb.Append("\b"); break;
-
case 'f':
-
sb.Append("\f"); break;
-
case ' ':
-
sb.Append("\n"); break;
-
case ' ':
-
sb.Append("\r"); break;
-
case ' ':
-
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