zoukankan      html  css  js  c++  java
  • 一个.NET通用JSON解析/构建类的实现(c#)

     

    在.NET Framework 3.5中已经提供了一个JSON对象的序列化工具,但是他是强类型的,必须先按JSON对象的格式定义一个类型,并将类型加上JSON序列化特性。本文将试图提供一个高度灵活的JSON通用类型(JsonObject),实现对JSON的解析及序列化。

    假设JSON对象内容如下:

    隐藏行号 复制代码 JSON
    1. {
    2. orders: {
    3. date: '21:31:59',
    4. name: 'Xfrog',
    5. books: [{
    6. name: 'C# 网络核心编程',
    7. publish: '2010-3-24'
    8. }, {
    9. name: 'C#入门经典中文版',
    10. publish: '2009-10-16'
    11. }]
    12.     },
    13. blog: 'http://www.cnblogs.com/xfrog'
    14. }

    使用JsonObject来构建,可选择以下三种方式:
    方式一:

    隐藏行号 复制代码 C#
    1. //通过标准构造函数
      
    2. JsonObject json = new JsonObject();
      
    3. json["orders"] = new JsonProperty(new JsonObject());
      
    4. json["blog"] = new JsonProperty("http://www.cnblogs.com/xfrog");
      
    5. 
      
    6. JsonObject config = json.Properties<JsonObject>("orders");
      
    7. json["orders"]["date"] = new JsonProperty(DateTime.Now.ToLongTimeString());
      
    8. json["orders"]["name"] = new JsonProperty("Xfrog");
      
    9. json["orders"]["books"] = new JsonProperty();
      
    10. 
      
    11. JsonProperty book = json["orders"]["books"].Add(new JsonObject());
      
    12. book["name"] = new JsonProperty("C# 网络核心编程");
      
    13. book["publish"] = new JsonProperty("2010-3-24");
      
    14. 
      
    15. book = json["orders"]["books"].Add(new JsonObject());
      
    16. book["name"] = new JsonProperty("C#入门经典中文版");
      
    17. book["publish"] = new JsonProperty("2009-10-16");
      


    方式二:

    隐藏行号 复制代码 C#
    1. //通过回调函数简化对象的构建
      
    2. JsonObject json2 = new JsonObject((a) =>
      
    3. {
      
    4.     a["orders"] = new JsonProperty(new JsonObject((b) =>
      
    5.     {
      
    6.         b["date"] = new JsonProperty(DateTime.Now.ToLongTimeString());
      
    7.         b["name"] = new JsonProperty("Xfrog");
      
    8.         b["books"] = new JsonProperty();
      
    9.         b["books"].Add(new JsonObject((c) =>
      
    10.         {
      
    11.             c["name"] = new JsonProperty("C# 网络核心编程");
      
    12.             c["publish"] = new JsonProperty("2010-3-24");
      
    13.         }));
      
    14.         b["books"].Add(new JsonObject((c) =>
      
    15.         {
      
    16.             c["name"] = new JsonProperty("C#入门经典中文版");
      
    17.             c["publish"] = new JsonProperty("2009-10-16");
      
    18.         }));
      
    19.     }));
      
    20.     a["blog"] = new JsonProperty("http://www.cnblogs.com/xfrog");
      
    21. });
      

    方式三:

    隐藏行号 复制代码 C#
    1. //通过字符串构建Json对象
      
    2. JsonObject newObj = new JsonObject(jsonStr);
      


    获取Json对象属性值的方法,也有三种方式:

    隐藏行号 复制代码 C#
    1. //通过泛型函数
      
    2. Console.WriteLine(newObj["orders"].GetValue<JsonObject>()["books"].GetValue<List<JsonProperty>>()[1].GetValue<JsonObject>()["name"].Value);
      
    3. //通过属性类型对应的属性
      
    4. Console.WriteLine(newObj["orders"].Object["books"].Items[1].Object["name"].Value);
      
    5. //如果属性为对象类型,可通过字符串索引简化
      
    6. Console.WriteLine(newObj["orders"]["books"][1]["name"].Value);
      

      通用类:代码
      /**********************************************************
       * 作者:wHaibo
       * Email:xfrogcn@163.com
       * 日期:2010-04-07
       * 版本:1.0
       * 说明:Json通用转换类
       *********************************************************/ 
      
      using System;
      using System.Collections.Generic;
      using System.Text;
      
      namespace Xfrog.Net
      {
      
          /// <summary>
          /// 用于构建属性值的回调
          /// </summary>
          /// <param name="Property"></param>
          public delegate void SetProperties(JsonObject Property);
      
          /// <summary>
          /// JsonObject属性值类型
          /// </summary>
          public enum JsonPropertyType
          {
              String,
              Object,
              Array,
              Number,
              Bool,
              Null
          }
      
          /// <summary>
          /// JSON通用对象
          /// </summary>
          public class JsonObject
          {
              private Dictionary<String, JsonProperty> _property;
      
              public JsonObject()
              {
                  this._property = null;
              }
      
              public JsonObject(String jsonString)
              {
                  this.Parse(ref jsonString);
              }
      
              public JsonObject(SetProperties callback)
              {
                  if (callback != null)
                  {
                      callback(this);
                  }
              }
      
              /// <summary>
              /// Json字符串解析
              /// </summary>
              /// <param name="jsonString"></param>
              private void Parse(ref String jsonString)
              {
                  int len = jsonString.Length;
                  bool poo = string.IsNullOrEmpty(jsonString);
                  string po = jsonString.Substring(0, 1);
                  string ll = jsonString.Substring(jsonString.Length - 1, 1);
                  if (String.IsNullOrEmpty(jsonString) || jsonString.Substring(0, 1) != "{" || jsonString.Substring(jsonString.Length - 1, 1) != "}")
                  {
                      throw new ArgumentException("传入文本不符合Json格式!" + jsonString);
                  }
                  Stack<Char> stack = new Stack<char>();
                  Stack<Char> stackType = new Stack<char>();
                  StringBuilder sb = new StringBuilder();
                  Char cur;
                  bool convert = false;
                  bool isValue = false;
                  JsonProperty last = null;
                  for (int i = 1; i <= len - 2; i++)
                  {
                      cur = jsonString[i];
                      if (cur == '}')
                      {
                          ;
                      }
                      if (cur == ' ' && stack.Count == 0)
                      {
                          ;
                      }
                      else if ((cur == '\'' || cur == '\"') && !convert && stack.Count == 0 && !isValue)
                      {
                          sb.Length = 0;
                          stack.Push(cur);
                      }
                      else if ((cur == '\'' || cur == '\"') && !convert && stack.Count > 0 && stack.Peek() == cur && !isValue)
                      {
                          stack.Pop();
                      }
                      else if ( (cur == '[' || cur == '{') && stack.Count == 0)
                      {
                          stackType.Push(cur == '[' ? ']' : '}');
                          sb.Append(cur);
                      }
                      else if ((cur == ']' || cur == '}') && stack.Count == 0 && stackType.Peek() == cur)
                      {
                          stackType.Pop();
                          sb.Append(cur);
                      }
                      else if (cur == ':' && stack.Count == 0 && stackType.Count == 0 && !isValue)
                      {
                          last = new JsonProperty();
                          this[sb.ToString()] = last;
                          isValue = true;
                          sb.Length = 0;
                      }
                      else if (cur == ',' && stack.Count == 0 && stackType.Count == 0)
                      {
                          if (last != null)
                          {
                              
                              String temp = sb.ToString();
                              last.Parse(ref temp);
                          }
                          isValue = false;
                          sb.Length = 0;
                      }
                      else
                      {
                          sb.Append(cur);
                      }
                  }
                  if (sb.Length > 0 && last != null && last.Type == JsonPropertyType.Null)
                  {
                      String temp = sb.ToString();
                      last.Parse(ref temp);
                  }
              }
      
              /// <summary>
              /// 获取属性
              /// </summary>
              /// <param name="PropertyName"></param>
              /// <returns></returns>
              public JsonProperty this[String PropertyName]
              {
                  get
                  {
                      JsonProperty result = null;
                      if (this._property != null && this._property.ContainsKey(PropertyName))
                      {
                          result = this._property[PropertyName];
                      }
                      return result;
                  }
                  set
                  {
                      if (this._property == null)
                      {
                          this._property = new Dictionary<string, JsonProperty>(StringComparer.OrdinalIgnoreCase);
                      }
                      if (this._property.ContainsKey(PropertyName))
                      {
                          this._property[PropertyName] = value;
                      }
                      else
                      {
                          this._property.Add(PropertyName, value);
                      }
                  }
              }
      
              /// <summary>
              /// 通过此泛型函数可直接获取指定类型属性的值
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="PropertyName"></param>
              /// <returns></returns>
              public virtual T Properties<T>(String PropertyName) where T : class
              {
                  JsonProperty p = this[PropertyName];
                  if (p != null)
                  {
                      return p.GetValue<T>();
                  }
                  return default(T);
              }
              
              /// <summary>
              /// 获取属性名称列表
              /// </summary>
              /// <returns></returns>
              public String[] GetPropertyNames()
              {
                  if (this._property == null)
                      return null;
                  String[] keys = null;
                  if (this._property.Count > 0)
                  {
                      keys = new String[this._property.Count];
                      this._property.Keys.CopyTo(keys, 0);
                  }
                  return keys;
              }
      
              /// <summary>
              /// 移除一个属性
              /// </summary>
              /// <param name="PropertyName"></param>
              /// <returns></returns>
              public JsonProperty RemoveProperty(String PropertyName)
              {
                  if (this._property != null && this._property.ContainsKey(PropertyName))
                  {
                      JsonProperty p = this._property[PropertyName];
                      this._property.Remove(PropertyName);
                      return p;
                  }
                  return null;
              }
      
              /// <summary>
              /// 是否为空对象
              /// </summary>
              /// <returns></returns>
              public bool IsNull()
              {
                  return this._property == null;
              }
      
              public override string ToString()
              {
                  return this.ToString("");
              }
      
              /// <summary>
              /// ToString...
              /// </summary>
              /// <param name="format">格式化字符串</param>
              /// <returns></returns>
              public virtual string ToString(String format)
              {
                  if (this.IsNull())
                  {
                      return "{}";
                  }
                  else
                  {
                      StringBuilder sb = new StringBuilder();
                      foreach (String key in this._property.Keys)
                      {
                          sb.Append(",");
                          sb.Append(key).Append(": ");
                          sb.Append(this._property[key].ToString(format));
      
                      }
                      if (this._property.Count > 0)
                      {
                          sb.Remove(0, 1);
                      }
                      sb.Insert(0, "{");
                      sb.Append("}");
                      return sb.ToString();
                  }
              }
          }
      
          /// <summary>
          /// JSON对象属性
          /// </summary>
          public class JsonProperty
          {
              private JsonPropertyType _type;
              private String _value;
              private JsonObject _object;
              private List<JsonProperty> _list;
              private bool _bool;
              private double _number;
      
              public JsonProperty()
              {
                  this._type = JsonPropertyType.Null;
                  this._value = null;
                  this._object = null;
                  this._list = null;
              }
      
              public JsonProperty(Object value)
              {
                  this.SetValue(value);
              }
      
      
              public JsonProperty(String jsonString)
              {
                  this.Parse(ref jsonString);
              }
       
      
              /// <summary>
              /// Json字符串解析
              /// </summary>
              /// <param name="jsonString"></param>
              public void Parse(ref String jsonString)
              {
                  if (String.IsNullOrEmpty(jsonString))
                  {
                      this.SetValue(null);
                  }
                  else
                  {
                      string first = jsonString.Substring(0, 1);
                      string last = jsonString.Substring(jsonString.Length - 1, 1);
                      if (first == "[" && last == "]")
                      {
                          this.SetValue(this.ParseArray(ref jsonString));
                      }
                      else if (first == "{" && last=="}")
                      {
                          this.SetValue(this.ParseObject(ref jsonString));
                      }
                      else if ((first == "'" || first == "\"") && first == last)
                      {
                         this.SetValue( this.ParseString(ref jsonString));
                      }
                      else if (jsonString == "true" || jsonString == "false")
                      {
                          this.SetValue(jsonString == "true" ? true : false);
                      }
                      else if (jsonString == "null")
                      {
                          this.SetValue(null);
                      }
                      else
                      {
                          double d = 0;
                          if (double.TryParse(jsonString, out d))
                          {
                              this.SetValue(d);
                          }
                          else
                          {
                              this.SetValue(jsonString);
                          }
                      }
                  }
              }
      
              /// <summary>
              /// Json Array解析
              /// </summary>
              /// <param name="jsonString"></param>
              /// <returns></returns>
              private List<JsonProperty> ParseArray(ref String jsonString)
              {
                  List<JsonProperty> list = new List<JsonProperty>();
                  int len = jsonString.Length;
                  StringBuilder sb = new StringBuilder();
                  Stack<Char> stack = new Stack<char>();
                  Stack<Char> stackType = new Stack<Char>();
                  bool conver = false;
                  Char cur;
                  for (int i = 1; i <= len - 2; i++)
                  {
                      cur = jsonString[i];
                      if (Char.IsWhiteSpace(cur) && stack.Count == 0)
                      {
                          ;
                      }
                      else if ((cur == '\'' && stack.Count == 0 && !conver && stackType.Count == 0) || (cur == '\"' && stack.Count == 0 && !conver && stackType.Count == 0))
                      {
                          sb.Length = 0;
                          sb.Append(cur);
                          stack.Push(cur);
                      }
                      else if (cur == '\\' && stack.Count > 0 && !conver)
                      {
                          sb.Append(cur);
                          conver = true;
                      }
                      else if (conver == true)
                      {
                          conver = false;
      
                          if (cur == 'u')
                          {
                              sb.Append(new char[] { cur, jsonString[i + 1], jsonString[i + 2], jsonString[i + 3] });
                              i += 4;
                          }
                          else
                          {
                              sb.Append(cur);
                          }
                      }
                      else if ((cur == '\'' || cur == '\"') && !conver && stack.Count>0 && stack.Peek() == cur && stackType.Count == 0)
                      {
                          sb.Append(cur);
                          list.Add(new JsonProperty(sb.ToString()));
                          stack.Pop();
                      }else if( (cur == '[' || cur == '{' ) && stack.Count==0 )
                      {
                          if (stackType.Count == 0)
                          {
                              sb.Length = 0;
                          }
                          sb.Append( cur);
                          stackType.Push((cur == '[' ? ']' : '}'));
                      }
                      else if ((cur == ']' || cur == '}') && stack.Count == 0 && stackType.Count>0 && stackType.Peek() == cur)
                      {
                          sb.Append(cur);
                          stackType.Pop();
                          if (stackType.Count == 0)
                          {
                              list.Add(new JsonProperty(sb.ToString()));
                              sb.Length = 0;
                          }
      
                      }
                      else if (cur == ',' && stack.Count == 0 && stackType.Count == 0)
                      {
                          if (sb.Length > 0)
                          {
                              list.Add(new JsonProperty(sb.ToString()));
                              sb.Length = 0;
                          }
                      }
                      else
                      {
                          sb.Append(cur);
                      }      
                  }
                  if (stack.Count > 0 || stackType.Count > 0)
                  {
                      list.Clear();
                      throw new ArgumentException("无法解析Json Array对象!");
                  }
                  else if (sb.Length > 0)
                  {
                      list.Add(new JsonProperty(sb.ToString()));
                  }
                  return list;
              }
      
      
              /// <summary>
              /// Json String解析
              /// </summary>
              /// <param name="jsonString"></param>
              /// <returns></returns>
              private String ParseString(ref String jsonString)
              { 
                  int len = jsonString.Length;
                  StringBuilder sb = new StringBuilder();
                  bool conver = false;
                  Char cur;
                  for (int i = 1; i <= len - 2; i++)
                  {
                      cur = jsonString[i];
                      if (cur == '\\' && !conver)
                      {
                          conver = true;
                      }
                      else if (conver == true)
                      {
                          conver = false;
                          if (cur == '\\' || cur == '\"' || cur == '\'' || cur == '/')
                          {
                              sb.Append(cur);
                          }
                          else
                          {
                              if (cur == 'u')
                              {
                                  String temp = new String(new char[] { cur, jsonString[i + 1], jsonString[i + 2], jsonString[i + 3] });
                                  sb.Append((char)Convert.ToInt32(temp, 16));
                                  i += 4;
                              }
                              else
                              {
                                  switch (cur)
                                  {
                                      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;
                                  }
                              }
                          }
                      }
                      else
                      {
                          sb.Append(cur);
                      }
                  }
                  return sb.ToString();
              }
      
              /// <summary>
              /// Json Object解析
              /// </summary>
              /// <param name="jsonString"></param>
              /// <returns></returns>
              private JsonObject ParseObject(ref String jsonString)
              {
                  return new JsonObject(jsonString);
              }
      
              /// <summary>
              /// 定义一个索引器,如果属性是非数组的,返回本身
              /// </summary>
              /// <param name="index"></param>
              /// <returns></returns>
              public JsonProperty this[int index]
              {
                  get
                  {
                      JsonProperty r = null;
                      if (this._type == JsonPropertyType.Array)
                      {
                          if (this._list != null && (this._list.Count - 1) >= index)
                          {
                              r = this._list[index];
                          }
                      }
                      else if (index == 0)
                      {
                          return this;
                      }
                      return r;
                  }
              }
      
              /// <summary>
              /// 提供一个字符串索引,简化对Object属性的访问
              /// </summary>
              /// <param name="PropertyName"></param>
              /// <returns></returns>
              public JsonProperty this[String PropertyName]
              {
                  get
                  {
                      if (this._type == JsonPropertyType.Object)
                      {
                          return this._object[PropertyName];
                      }
                      else
                      {
                          return null;
                      }
                  }
                  set
                  {
                      if (this._type == JsonPropertyType.Object)
                      {
                          this._object[PropertyName] = value;
                      }
                      else
                      {
                          throw new NotSupportedException("Json属性不是对象类型!");
                      }
                  }
              }
      
              /// <summary>
              /// JsonObject值
              /// </summary>
              public JsonObject Object
              {
                  get
                  {
                      if (this._type == JsonPropertyType.Object)
                          return this._object;
                      return null;
                  }
              }
      
              /// <summary>
              /// 字符串值
              /// </summary>
              public String Value
              {
                  get
                  {
                      if (this._type == JsonPropertyType.String)
                      {
                          return this._value;
                      }
                      else if (this._type == JsonPropertyType.Number)
                      {
                          return this._number.ToString();
                      }
                      return null;
                  }
              }
      
              public JsonProperty Add(Object value)
              {
                  if (this._type != JsonPropertyType.Null && this._type != JsonPropertyType.Array)
                  {
                      throw new NotSupportedException("Json属性不是Array类型,无法添加元素!");
                  }
                  if (this._list == null)
                  {
                      this._list = new List<JsonProperty>();
                  }
                  JsonProperty jp = new JsonProperty(value);
                  this._list.Add(jp);
                  this._type = JsonPropertyType.Array;
                  return jp;
              }
      
              /// <summary>
              /// Array值,如果属性是非数组的,则封装成只有一个元素的数组
              /// </summary>
              public List<JsonProperty> Items
              {
                  get
                  {
                      if (this._type == JsonPropertyType.Array)
                      {
                          return this._list;
                      }
                      else
                      {
                          List<JsonProperty> list = new List<JsonProperty>();
                          list.Add(this);
                          return list;
                      }
                  }
              }
      
              /// <summary>
              /// 数值
              /// </summary>
              public double Number
              {
                  get
                  {
                      if (this._type == JsonPropertyType.Number)
                      {
                          return this._number;
                      }
                      else
                      {
                          return double.NaN;
                      }
                  }
              }
      
              public void Clear()
              {
                  this._type = JsonPropertyType.Null;
                  this._value = String.Empty;
                  this._object = null;
                  if (this._list != null)
                  {
                      this._list.Clear();
                      this._list = null;
                  }
              }
      
              public Object GetValue()
              {
                  if (this._type == JsonPropertyType.String)
                  {
                      return this._value;
                  }
                  else if (this._type == JsonPropertyType.Object)
                  {
                      return this._object;
                  }
                  else if (this._type == JsonPropertyType.Array)
                  {
                      return this._list;
                  }
                  else if (this._type == JsonPropertyType.Bool)
                  {
                      return this._bool;
                  }
                  else if (this._type == JsonPropertyType.Number)
                  {
                      return this._number;
                  }
                  else
                  {
                      return null;
                  }
              }
      
              public virtual T GetValue<T>() where T : class
              {
                  return (GetValue() as T);
              }
      
              public virtual void SetValue(Object value)
              {
                  if (value is String)
                  {
                      this._type = JsonPropertyType.String;
                      this._value = (String)value;
                  }
                  else if (value is List<JsonProperty>)
                  {
                      this._list = ((List<JsonProperty>)value);
                      this._type = JsonPropertyType.Array;
                  }
                  else if (value is JsonObject)
                  {
                      this._object = (JsonObject)value;
                      this._type = JsonPropertyType.Object;
                  }
                  else if (value is bool)
                  {
                      this._bool = (bool)value;
                      this._type = JsonPropertyType.Bool;
                  }
                  else if (value == null)
                  {
                      this._type = JsonPropertyType.Null;
                  }
                  else
                  {
                      double d = 0;
                      if (double.TryParse(value.ToString(), out d))
                      {
                          this._number = d;
                          this._type = JsonPropertyType.Number;
                      }
                      else
                      {
                          throw new ArgumentException("错误的参数类型!");
                      }
                  }
              }
      
              public virtual int Count
              {
                  get
                  {
                      int c = 0;
                      if (this._type == JsonPropertyType.Array)
                      {
                          if (this._list != null)
                          {
                              c = this._list.Count;
                          }
                      }
                      else
                      {
                          c = 1;
                      }
                      return c;
                  }
              }
      
              public JsonPropertyType Type
              {
                  get { return this._type; }
              }
      
              public override string ToString()
              {
                  return this.ToString("");
              }
      
      
              public virtual string ToString(String format)
              {
                  StringBuilder sb = new StringBuilder();
                  if (this._type == JsonPropertyType.String)
                  {
                      sb.Append("'").Append(this._value).Append("'");
                      return sb.ToString();
                  }
                  else if (this._type == JsonPropertyType.Bool)
                  {
                      return this._bool ? "true" : "false";
                  }
                  else if (this._type == JsonPropertyType.Number)
                  {
                      return this._number.ToString();
                  }
                  else if (this._type == JsonPropertyType.Null)
                  {
                      return "null";
                  }
                  else if (this._type == JsonPropertyType.Object)
                  {
                      return this._object.ToString();
                  }
                  else
                  {
                      if (this._list == null || this._list.Count == 0)
                      {
                          sb.Append("[]");
                      }
                      else
                      {
                          sb.Append("[");
                          if (this._list.Count > 0)
                          {
                              foreach (JsonProperty p in this._list)
                              {
                                  sb.Append(p.ToString());
                                  sb.Append(", ");
                              }
                              sb.Length-=2;
                          }
                          sb.Append("]");
                      }
                      return sb.ToString();
                  }
              }
          }
      }
      
      
      

        

      
      

        

    直接使用ToString函数,将JsonObject转换为Json字符串:

    隐藏行号 复制代码 C#
    1. String jsonStr = json.ToString();
      

    注意:

    我在重载ToString函数时,并没有将字符串转换为JavsScript字符串类型(即对需要转义的字符的处理),当然,要实现也是极其简单的。另外,对于带String参数的ToString,我也为做特殊处理,感兴趣的朋友可自行实现。

    Technorati 标签: .NET,JSON,C#

    源代码下载

  • 相关阅读:
    域名和dns
    Oracle版本区别及版本选择!
    并发
    URL和URI的区别??
    sshpass免密码(免交互)连接
    python之路 目录
    awk sed 总结
    aiohttp使用
    Mac破解软件 “XXX”意外退出 奔溃解决方法
    我的Mac中毒了,病毒居然叫做MacPerformance
  • 原文地址:https://www.cnblogs.com/xiaofengfeng/p/2434444.html
Copyright © 2011-2022 走看看