把對象轉化為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