zoukankan      html  css  js  c++  java
  • C#中如何实现json转化时只处理部分属性

    把对象转化为json字符串,很常用,但如果因为现在大部分项目都是用了ORM映射,导致一个对象的属性特别多,如果前台只需要部分属性如何实现?

    当然最简单是所有属性都json化,前台只处理需要的属性,多余的不管。那有没有一种方式可以实现,对于同一种类型,按照前台的需要只处理json需要的属性呢?

    .Net中把对象转为json字符串主要有四种方式:具体参考

    1自己转化灵活,但难度大,能实现。

    2使用Newtonsoft.Json,看了一下官方文档,似乎不能实现,能忽略默认,空值等属性,也可以控制json时输出那些属性,但需要使用特性,也就是说,对于指定的类型,json输出的属性是确定的,不能动态改变。

    具体可参考

    3使用JavaScriptSerializer类,查看了官方文档,没找到方法,不能实现

    4也是使用的是特性,没找到方法,不能实现。

    没有现成的方法,也就只能自己实现了。我们知道把对象转化为json字符串,核心自然是使用反射得到需要的属性和属性的值。但如果属性是一个类对象呢?,数组或者是泛型呢?

    另外如果字符串中包含特殊字符如何处理?

    于是自己也就实现了一个简单的

    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 '':
    136.  
      sb.Append("\b"); break;
    137.  
      case 'f':
    138.  
      sb.Append("\f"); break;
    139.  
      case ' ':
    140.  
      sb.Append("\n"); break;
    141.  
      case ' ':
    142.  
      sb.Append("\r"); break;
    143.  
      case ' ':
    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

  • 相关阅读:
    ANDROID_MARS学习笔记_S01原始版_009_下载文件
    ANDROID_MARS学习笔记_S01原始版_009_SQLite
    ANDROID_MARS学习笔记_S01原始版_008_LooperBundle异步消息处理
    ANDROID_MARS学习笔记_S01原始版_008_Handler(异步消息处理机制)
    ANDROID_MARS学习笔记_S01原始版_007_Handler及线程的简单使用
    ANDROID_MARS学习笔记_S01原始版_006_ListView
    ANDROID_MARS学习笔记_S01原始版_005_ProgressBar
    ios Quartz 各种绘制图形用法
    ios 在UIView上画图,线条
    ios 内存管理
  • 原文地址:https://www.cnblogs.com/mq0036/p/9411488.html
Copyright © 2011-2022 走看看