C#中如何實現json轉化時只處理部分屬性

把對象轉化爲json字符串,很經常使用,但若是由於如今大部分項目都是用了ORM映射,致使一個對象的屬性特別多,若是前臺只須要部分屬性如何實現?html

固然最簡單是全部屬性都json化,前臺只處理須要的屬性,多餘的無論。那有沒有一種方式能夠實現,對於同一種類型,按照前臺的須要只處理json須要的屬性呢?shell

.Net中把對象轉爲json字符串主要有四種方式:具體參考json

1本身轉化靈活,但難度大,能實現。數組

2使用Newtonsoft.Json,看了一下官方文檔,彷佛不能實現,能忽略默認,空值等屬性,也能夠控制json時輸出那些屬性,但須要使用特性,也就是說,對於指定的類型,json輸出的屬性是肯定的,不能動態改變。
ide

具體可參考ui

3使用JavaScriptSerializer類,查看了官方文檔,沒找到方法,不能實現spa

4也是使用的是特性,沒找到方法,不能實現。.net

 

沒有現成的方法,也就只能本身實現了。咱們知道把對象轉化爲json字符串,核心天然是使用反射獲得須要的屬性和屬性的值。但若是屬性是一個類對象呢?,數組或者是泛型呢?code

另外若是字符串中包含特殊字符如何處理?orm

因而本身也就實現了一個簡單的

 

 

  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.  
    }
  38.  
    /// <summary>
  39.  
    /// 按照數字格式輸入的類型
  40.  
    /// </summary>
  41.  
    private static readonly List<Type> TypeNumCodeList = new List<Type>{
  42.  
    { typeof( sbyte)},
  43.  
    { typeof( sbyte?)},
  44.  
    { typeof( short)},
  45.  
    { typeof( short?)},
  46.  
    { typeof( ushort)},
  47.  
    { typeof( ushort?)},
  48.  
    { typeof( int)},
  49.  
    { typeof( int?)},
  50.  
    { typeof( byte)},
  51.  
    { typeof( byte?)},
  52.  
    { typeof( uint)},
  53.  
    { typeof( uint?)},
  54.  
    { typeof( long)},
  55.  
    { typeof( long?)},
  56.  
    { typeof( ulong)},
  57.  
    { typeof( ulong?)},
  58.  
    { typeof( float)},
  59.  
    { typeof( float?)},
  60.  
    { typeof( double) },
  61.  
    { typeof( double?)},
  62.  
    { typeof( decimal)},
  63.  
    { typeof( decimal?)},
  64.  
    { typeof( bool)},
  65.  
    { typeof( bool?)}
  66.  
    };
  67.  
    /// <summary>
  68.  
    /// 按照文字格式輸入的類型
  69.  
    /// </summary>
  70.  
    private static readonly List<Type> TypeStrCodeList = new List<Type>{
  71.  
    { typeof( char)},
  72.  
    { typeof( char?)},
  73.  
    { typeof(DateTime)},
  74.  
    { typeof(DateTime?)}
  75.  
    };
  76.  
    /// <summary>
  77.  
    /// 根據字段類型進行羅列,顯然不能處理全部的類型,也沒有處理字段是數組,對象的狀況
  78.  
    /// </summary>
  79.  
    /// <param name="propertytype"></param>
  80.  
    /// <param name="value"></param>
  81.  
    /// <param name="propertyName"></param>
  82.  
    /// <returns></returns>
  83.  
    private static string PropertyTypeValue(Type propertytype, object value, string propertyName)
  84.  
    {
  85.  
    string valueStr = value != null ? value.ToString() : "";
  86.  
    string returnStr = "";
  87.  
    if (TypeNumCodeList.Contains(propertytype))
  88.  
    {
  89.  
    if (! string.IsNullOrEmpty(valueStr)) //忽略掉空值
  90.  
    {
  91.  
    returnStr = string.Format( "\"{0}\":{1},", propertyName, valueStr);
  92.  
    }
  93.  
    }
  94.  
    else if (TypeStrCodeList.Contains(propertytype))
  95.  
    {
  96.  
    if (! string.IsNullOrEmpty(valueStr)) //忽略掉空值
  97.  
    {
  98.  
    returnStr = string.Format( "\"{0}\":\"{1}\",", propertyName, valueStr);
  99.  
    }
  100.  
    }
  101.  
    else if (propertytype == typeof( string))
  102.  
    {
  103.  
    if (! string.IsNullOrEmpty(valueStr)) //忽略掉空值,並處理字符串中的特殊字符
  104.  
    {
  105.  
    returnStr = string.Format( "\"{0}\":\"{1}\",", propertyName, String2Json(valueStr));
  106.  
    }
  107.  
    }
  108.  
    else //對象,數組等不能處理,
  109.  
     
  110.  
    {
  111.  
    returnStr = string.Format( "\"{0}\":\"{1}\",", propertyName, String2Json(valueStr));
  112.  
    }
  113.  
    return returnStr;
  114.  
    }
  115.  
     
  116.  
    /// <summary>
  117.  
    /// 過濾特殊字符
  118.  
    /// </summary>
  119.  
    /// <param name="s"></param>
  120.  
    /// <returns></returns>
  121.  
    private static string String2Json(string s)
  122.  
    {
  123.  
    StringBuilder sb = new StringBuilder();
  124.  
    for ( int i = 0; i < s.Length; i++)
  125.  
    {
  126.  
    char c = s.ToCharArray()[i];
  127.  
    switch (c)
  128.  
    {
  129.  
    case '\"':
  130.  
    sb.Append( "\\\""); break;
  131.  
    case '\\':
  132.  
    sb.Append( "\\\\"); break;
  133.  
    case '/':
  134.  
    sb.Append( "\\/"); break;
  135.  
    case '\b':
  136.  
    sb.Append( "\\b"); break;
  137.  
    case '\f':
  138.  
    sb.Append( "\\f"); break;
  139.  
    case '\n':
  140.  
    sb.Append( "\\n"); break;
  141.  
    case '\r':
  142.  
    sb.Append( "\\r"); break;
  143.  
    case '\t':
  144.  
    sb.Append( "\\t"); break;
  145.  
    /* case '<':
  146.  
    sb.Append("<"); break;
  147.  
    case '>':
  148.  
    sb.Append(">"); break;*/
  149.  
    default:
  150.  
    if ((c >= 0 && c <= 31) || c == 127) //在ASCⅡ碼中,第0~31號及第127號(共33個)是控制字符或通信專用字符
  151.  
    {
  152.  
     
  153.  
    }
  154.  
    else
  155.  
    {
  156.  
    sb.Append(c);
  157.  
    }
  158.  
    break;
  159.  
    }
  160.  
    }
  161.  
    return sb.ToString();
  162.  
    }


 


很顯然,這個實現有很大的問題,字符串中包含的特殊字符不必定處理完了,泛型,數組等屬性都沒有處理,可是簡單對象仍是能夠處理的。

 

既然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.  
    };
  42.  
     
  43.  
    /// <summary>
  44.  
    /// 把對象轉化爲json字符串,依然不能處理屬性是泛型,數組,對象等類型
  45.  
    /// </summary>
  46.  
    /// <typeparam name="T">須要轉化的對象的類型</typeparam>
  47.  
    /// <param name="t">須要轉化的對象</param>
  48.  
    /// <param name="propertyInfos">須要轉換的字段列表,用逗號分隔</param>
  49.  
    /// <returns></returns>
  50.  
    public static string ConvertFromModeTojson<T>(T t, string propertyInfos) where T : class
  51.  
    {
  52.  
    StringWriter sw = new StringWriter();
  53.  
    using (JsonTextWriter writer = new JsonTextWriter(sw))
  54.  
    {
  55.  
    writer.WriteStartObject();
  56.  
    string[] cols = propertyInfos.Split( new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
  57.  
    foreach ( string col in cols)
  58.  
    {
  59.  
    Type type = t.GetType();
  60.  
    PropertyInfo pinfo = type.GetProperty(col); //使用反射得到屬性
  61.  
    if (pinfo != null)
  62.  
    {
  63.  
    object v = pinfo.GetValue(t, null); //使用反射得到屬性的值
  64.  
    Type pinfoType = pinfo.PropertyType;
  65.  
    if (TypeCodeList.Contains(pinfoType))
  66.  
    {
  67.  
    writer.WritePropertyName(col);
  68.  
    writer.WriteValue(v);
  69.  
    }
  70.  
    else
  71.  
    { //其餘類型的忽略,避免異常
  72.  
     
  73.  
    }
  74.  
    }
  75.  
    else
  76.  
    {
  77.  
    throw new Exception( "不存在屬性" + col);
  78.  
    }
  79.  
    }
  80.  
    writer.WriteEndObject();
  81.  
    writer.Flush();
  82.  
    }
  83.  
    string jsonText = sw.GetStringBuilder().ToString();
  84.  
    return jsonText;
  85.  
    }


 

 


 

 

在前面的文章中使用的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.  
     
  48.  
    private readonly List< string> _propertyNames;
  49.  
    public DynamicContractResolver(List<string> propertyNames)
  50.  
    {
  51.  
    _propertyNames = propertyNames;
  52.  
    }
  53.  
    /// <summary>
  54.  
    /// 若是屬性是對象,須要把這個對象的屬性也傳給propertyNames,
  55.  
    /// 不然處理這個對象屬性時,就不包含對應的屬性值
  56.  
    /// </summary>
  57.  
    /// <param name="type"></param>
  58.  
    /// <param name="memberSerialization"></param>
  59.  
    /// <returns></returns>
  60.  
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  61.  
    {
  62.  
    IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
  63.  
    IList<JsonProperty> propertiesReturn = new List<JsonProperty>(); //須要json處理的屬性
  64.  
    foreach (JsonProperty item in properties)
  65.  
  66.  
     
  67.  
    string PropertyNameTemp = item.PropertyName.ToLower().Trim();
  68.  
    if (_propertyNames.Contains(PropertyNameTemp))
  69.  
    {
  70.  
    propertiesReturn.Add(item);
  71.  
    }
  72.  
    }
  73.  
     
  74.  
    return propertiesReturn;
  75.  
    }
  76.  
    }

 

 

出處:

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

相關文章
相關標籤/搜索