一个.NET通用JSON解析/构建类的实现(c#)

来源:互联网 发布:php江湖游戏源码 编辑:程序博客网 时间:2024/05/29 16:50

在.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. JsonObject config = json.Properties<JsonObject>("orders");
  6. json["orders"]["date"] = new JsonProperty(DateTime.Now.ToLongTimeString());
  7. json["orders"]["name"] = new JsonProperty("Xfrog");
  8. json["orders"]["books"] = new JsonProperty();
  9. JsonProperty book = json["orders"]["books"].Add(new JsonObject());
  10. book["name"] = new JsonProperty("C# 网络核心编程");
  11. book["publish"] = new JsonProperty("2010-3-24");
  12. book = json["orders"]["books"].Add(new JsonObject());
  13. book["name"] = new JsonProperty("C#入门经典中文版");
  14. 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;
    usingSystem.Text;
    namespaceXfrog.Net
    {
    /// <summary>
    /// 用于构建属性值的回调
    /// </summary>
    /// <param name="Property"></param>
    publicdelegate voidSetProperties(JsonObject Property);
    /// <summary>
    /// JsonObject属性值类型
    /// </summary>
    publicenum JsonPropertyType
    {
    String,
    Object,
    Array,
    Number,
    Bool,
    Null
    }
    /// <summary>
    /// JSON通用对象
    /// </summary>
    publicclass JsonObject
    {
    privateDictionary<String, JsonProperty> _property;
    publicJsonObject()
    {
    this._property =null;
    }
    publicJsonObject(String jsonString)
    {
    this.Parse(refjsonString);
    }
    publicJsonObject(SetProperties callback)
    {
    if(callback != null)
    {
    callback(this);
    }
    }
    /// <summary>
    /// Json字符串解析
    /// </summary>
    /// <param name="jsonString"></param>
    privatevoid Parse(refString jsonString)
    {
    intlen = jsonString.Length;
    boolpoo = string.IsNullOrEmpty(jsonString);
    stringpo = jsonString.Substring(0, 1);
    stringll = jsonString.Substring(jsonString.Length - 1, 1);
    if(String.IsNullOrEmpty(jsonString) || jsonString.Substring(0, 1) !="{" || jsonString.Substring(jsonString.Length - 1, 1) !="}")
    {
    thrownew ArgumentException("传入文本不符合Json格式!"+ jsonString);
    }
    Stack<Char> stack =new Stack<char>();
    Stack<Char> stackType =new Stack<char>();
    StringBuilder sb =new StringBuilder();
    Char cur;
    boolconvert = false;
    boolisValue = false;
    JsonProperty last =null;
    for(int i = 1; i <= len - 2; i++)
    {
    cur = jsonString[i];
    if(cur == '}')
    {
    ;
    }
    if(cur == ' ' && stack.Count == 0)
    {
    ;
    }
    elseif ((cur == '\'' || cur == '\"') && !convert && stack.Count == 0 && !isValue)
    {
    sb.Length = 0;
    stack.Push(cur);
    }
    elseif ((cur == '\'' || cur == '\"') && !convert && stack.Count > 0 && stack.Peek() == cur && !isValue)
    {
    stack.Pop();
    }
    elseif ( (cur == '[' || cur == '{') && stack.Count == 0)
    {
    stackType.Push(cur =='[' ? ']' : '}');
    sb.Append(cur);
    }
    elseif ((cur == ']' || cur == '}') && stack.Count == 0 && stackType.Peek() == cur)
    {
    stackType.Pop();
    sb.Append(cur);
    }
    elseif (cur == ':' && stack.Count == 0 && stackType.Count == 0 && !isValue)
    {
    last =new JsonProperty();
    this[sb.ToString()] = last;
    isValue =true;
    sb.Length = 0;
    }
    elseif (cur == ',' && stack.Count == 0 && stackType.Count == 0)
    {
    if(last != null)
    {
    String temp = sb.ToString();
    last.Parse(reftemp);
    }
    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(reftemp);
    }
    }
    /// <summary>
    /// 获取属性
    /// </summary>
    /// <param name="PropertyName"></param>
    /// <returns></returns>
    publicJsonProperty this[String PropertyName]
    {
    get
    {
    JsonProperty result =null;
    if(this._property !=null && this._property.ContainsKey(PropertyName))
    {
    result =this._property[PropertyName];
    }
    returnresult;
    }
    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>
    publicvirtual T Properties<T>(String PropertyName) where T :class
    {
    JsonProperty p =this[PropertyName];
    if(p != null)
    {
    returnp.GetValue<T>();
    }
    returndefault(T);
    }
    /// <summary>
    /// 获取属性名称列表
    /// </summary>
    /// <returns></returns>
    publicString[] GetPropertyNames()
    {
    if(this._property ==null)
    returnnull;
    String[] keys =null;
    if(this._property.Count > 0)
    {
    keys =new String[this._property.Count];
    this._property.Keys.CopyTo(keys, 0);
    }
    returnkeys;
    }
    /// <summary>
    /// 移除一个属性
    /// </summary>
    /// <param name="PropertyName"></param>
    /// <returns></returns>
    publicJsonProperty RemoveProperty(String PropertyName)
    {
    if(this._property !=null && this._property.ContainsKey(PropertyName))
    {
    JsonProperty p =this._property[PropertyName];
    this._property.Remove(PropertyName);
    returnp;
    }
    returnnull;
    }
    /// <summary>
    /// 是否为空对象
    /// </summary>
    /// <returns></returns>
    publicbool IsNull()
    {
    returnthis._property == null;
    }
    publicoverride stringToString()
    {
    returnthis.ToString("");
    }
    /// <summary>
    /// ToString...
    /// </summary>
    /// <param name="format">格式化字符串</param>
    /// <returns></returns>
    publicvirtual stringToString(String format)
    {
    if(this.IsNull())
    {
    return"{}";
    }
    else
    {
    StringBuilder sb =new StringBuilder();
    foreach(String key inthis._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("}");
    returnsb.ToString();
    }
    }
    }
    /// <summary>
    /// JSON对象属性
    /// </summary>
    publicclass JsonProperty
    {
    privateJsonPropertyType _type;
    privateString _value;
    privateJsonObject _object;
    privateList<JsonProperty> _list;
    privatebool _bool;
    privatedouble _number;
    publicJsonProperty()
    {
    this._type = JsonPropertyType.Null;
    this._value =null;
    this._object =null;
    this._list =null;
    }
    publicJsonProperty(Object value)
    {
    this.SetValue(value);
    }
    publicJsonProperty(String jsonString)
    {
    this.Parse(refjsonString);
    }
    /// <summary>
    /// Json字符串解析
    /// </summary>
    /// <param name="jsonString"></param>
    publicvoid Parse(refString jsonString)
    {
    if(String.IsNullOrEmpty(jsonString))
    {
    this.SetValue(null);
    }
    else
    {
    stringfirst = jsonString.Substring(0, 1);
    stringlast = jsonString.Substring(jsonString.Length - 1, 1);
    if(first == "["&& last == "]")
    {
    this.SetValue(this.ParseArray(refjsonString));
    }
    elseif (first == "{" && last=="}")
    {
    this.SetValue(this.ParseObject(refjsonString));
    }
    elseif ((first == "'" || first == "\"") && first == last)
    {
    this.SetValue(this.ParseString(refjsonString));
    }
    elseif (jsonString == "true" || jsonString =="false")
    {
    this.SetValue(jsonString =="true" ? true : false);
    }
    elseif (jsonString == "null")
    {
    this.SetValue(null);
    }
    else
    {
    doubled = 0;
    if(double.TryParse(jsonString,out d))
    {
    this.SetValue(d);
    }
    else
    {
    this.SetValue(jsonString);
    }
    }
    }
    }
    /// <summary>
    /// Json Array解析
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    privateList<JsonProperty> ParseArray(refString jsonString)
    {
    List<JsonProperty> list =new List<JsonProperty>();
    intlen = jsonString.Length;
    StringBuilder sb =new StringBuilder();
    Stack<Char> stack =new Stack<char>();
    Stack<Char> stackType =new Stack<Char>();
    boolconver = false;
    Char cur;
    for(int i = 1; i <= len - 2; i++)
    {
    cur = jsonString[i];
    if(Char.IsWhiteSpace(cur) && stack.Count == 0)
    {
    ;
    }
    elseif ((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);
    }
    elseif (cur == '\\' && stack.Count > 0 && !conver)
    {
    sb.Append(cur);
    conver =true;
    }
    elseif (conver == true)
    {
    conver =false;
    if(cur == 'u')
    {
    sb.Append(newchar[] { cur, jsonString[i + 1], jsonString[i + 2], jsonString[i + 3] });
    i += 4;
    }
    else
    {
    sb.Append(cur);
    }
    }
    elseif ((cur == '\'' || cur == '\"') && !conver && stack.Count>0 && stack.Peek() == cur && stackType.Count == 0)
    {
    sb.Append(cur);
    list.Add(newJsonProperty(sb.ToString()));
    stack.Pop();
    }elseif( (cur == '[' || cur == '{' ) && stack.Count==0 )
    {
    if(stackType.Count == 0)
    {
    sb.Length = 0;
    }
    sb.Append( cur);
    stackType.Push((cur =='[' ? ']' : '}'));
    }
    elseif ((cur == ']' || cur == '}') && stack.Count == 0 && stackType.Count>0 && stackType.Peek() == cur)
    {
    sb.Append(cur);
    stackType.Pop();
    if(stackType.Count == 0)
    {
    list.Add(newJsonProperty(sb.ToString()));
    sb.Length = 0;
    }
    }
    elseif (cur == ',' && stack.Count == 0 && stackType.Count == 0)
    {
    if(sb.Length > 0)
    {
    list.Add(newJsonProperty(sb.ToString()));
    sb.Length = 0;
    }
    }
    else
    {
    sb.Append(cur);
    }
    }
    if(stack.Count > 0 || stackType.Count > 0)
    {
    list.Clear();
    thrownew ArgumentException("无法解析Json Array对象!");
    }
    elseif (sb.Length > 0)
    {
    list.Add(newJsonProperty(sb.ToString()));
    }
    returnlist;
    }
    /// <summary>
    /// Json String解析
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    privateString ParseString(refString jsonString)
    {
    intlen = jsonString.Length;
    StringBuilder sb =new StringBuilder();
    boolconver = false;
    Char cur;
    for(int i = 1; i <= len - 2; i++)
    {
    cur = jsonString[i];
    if(cur == '\\'&& !conver)
    {
    conver =true;
    }
    elseif (conver == true)
    {
    conver =false;
    if(cur == '\\'|| cur == '\"'|| cur == '\''|| cur == '/')
    {
    sb.Append(cur);
    }
    else
    {
    if(cur == 'u')
    {
    String temp =new String(newchar[] { 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);
    }
    }
    returnsb.ToString();
    }
    /// <summary>
    /// Json Object解析
    /// </summary>
    /// <param name="jsonString"></param>
    /// <returns></returns>
    privateJsonObject ParseObject(refString jsonString)
    {
    returnnew JsonObject(jsonString);
    }
    /// <summary>
    /// 定义一个索引器,如果属性是非数组的,返回本身
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    publicJsonProperty this[intindex]
    {
    get
    {
    JsonProperty r =null;
    if(this._type == JsonPropertyType.Array)
    {
    if(this._list !=null && (this._list.Count - 1) >= index)
    {
    r =this._list[index];
    }
    }
    elseif (index == 0)
    {
    returnthis;
    }
    returnr;
    }
    }
    /// <summary>
    /// 提供一个字符串索引,简化对Object属性的访问
    /// </summary>
    /// <param name="PropertyName"></param>
    /// <returns></returns>
    publicJsonProperty this[String PropertyName]
    {
    get
    {
    if(this._type == JsonPropertyType.Object)
    {
    returnthis._object[PropertyName];
    }
    else
    {
    returnnull;
    }
    }
    set
    {
    if(this._type == JsonPropertyType.Object)
    {
    this._object[PropertyName] = value;
    }
    else
    {
    thrownew NotSupportedException("Json属性不是对象类型!");
    }
    }
    }
    /// <summary>
    /// JsonObject值
    /// </summary>
    publicJsonObject Object
    {
    get
    {
    if(this._type == JsonPropertyType.Object)
    returnthis._object;
    returnnull;
    }
    }
    /// <summary>
    /// 字符串值
    /// </summary>
    publicString Value
    {
    get
    {
    if(this._type == JsonPropertyType.String)
    {
    returnthis._value;
    }
    elseif (this._type == JsonPropertyType.Number)
    {
    returnthis._number.ToString();
    }
    returnnull;
    }
    }
    publicJsonProperty Add(Object value)
    {
    if(this._type != JsonPropertyType.Null &&this._type != JsonPropertyType.Array)
    {
    thrownew 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;
    returnjp;
    }
    /// <summary>
    /// Array值,如果属性是非数组的,则封装成只有一个元素的数组
    /// </summary>
    publicList<JsonProperty> Items
    {
    get
    {
    if(this._type == JsonPropertyType.Array)
    {
    returnthis._list;
    }
    else
    {
    List<JsonProperty> list =new List<JsonProperty>();
    list.Add(this);
    returnlist;
    }
    }
    }
    /// <summary>
    /// 数值
    /// </summary>
    publicdouble Number
    {
    get
    {
    if(this._type == JsonPropertyType.Number)
    {
    returnthis._number;
    }
    else
    {
    returndouble.NaN;
    }
    }
    }
    publicvoid Clear()
    {
    this._type = JsonPropertyType.Null;
    this._value = String.Empty;
    this._object =null;
    if(this._list !=null)
    {
    this._list.Clear();
    this._list =null;
    }
    }
    publicObject GetValue()
    {
    if(this._type == JsonPropertyType.String)
    {
    returnthis._value;
    }
    elseif (this._type == JsonPropertyType.Object)
    {
    returnthis._object;
    }
    elseif (this._type == JsonPropertyType.Array)
    {
    returnthis._list;
    }
    elseif (this._type == JsonPropertyType.Bool)
    {
    returnthis._bool;
    }
    elseif (this._type == JsonPropertyType.Number)
    {
    returnthis._number;
    }
    else
    {
    returnnull;
    }
    }
    publicvirtual T GetValue<T>() where T :class
    {
    return(GetValue() asT);
    }
    publicvirtual voidSetValue(Object value)
    {
    if(value is String)
    {
    this._type = JsonPropertyType.String;
    this._value = (String)value;
    }
    elseif (value isList<JsonProperty>)
    {
    this._list = ((List<JsonProperty>)value);
    this._type = JsonPropertyType.Array;
    }
    elseif (value isJsonObject)
    {
    this._object = (JsonObject)value;
    this._type = JsonPropertyType.Object;
    }
    elseif (value isbool)
    {
    this._bool = (bool)value;
    this._type = JsonPropertyType.Bool;
    }
    elseif (value == null)
    {
    this._type = JsonPropertyType.Null;
    }
    else
    {
    doubled = 0;
    if(double.TryParse(value.ToString(),out d))
    {
    this._number = d;
    this._type = JsonPropertyType.Number;
    }
    else
    {
    thrownew ArgumentException("错误的参数类型!");
    }
    }
    }
    publicvirtual intCount
    {
    get
    {
    intc = 0;
    if(this._type == JsonPropertyType.Array)
    {
    if(this._list !=null)
    {
    c =this._list.Count;
    }
    }
    else
    {
    c = 1;
    }
    returnc;
    }
    }
    publicJsonPropertyType Type
    {
    get{ return this._type; }
    }
    publicoverride stringToString()
    {
    returnthis.ToString("");
    }
    publicvirtual stringToString(String format)
    {
    StringBuilder sb =new StringBuilder();
    if(this._type == JsonPropertyType.String)
    {
    sb.Append("'").Append(this._value).Append("'");
    returnsb.ToString();
    }
    elseif (this._type == JsonPropertyType.Bool)
    {
    returnthis._bool ? "true" : "false";
    }
    elseif (this._type == JsonPropertyType.Number)
    {
    returnthis._number.ToString();
    }
    elseif (this._type == JsonPropertyType.Null)
    {
    return"null";
    }
    elseif (this._type == JsonPropertyType.Object)
    {
    returnthis._object.ToString();
    }
    else
    {
    if(this._list ==null || this._list.Count == 0)
    {
    sb.Append("[]");
    }
    else
    {
    sb.Append("[");
    if(this._list.Count > 0)
    {
    foreach(JsonProperty p inthis._list)
    {
    sb.Append(p.ToString());
    sb.Append(", ");
    }
    sb.Length-=2;
    }
    sb.Append("]");
    }
    returnsb.ToString();
    }
    }
    }
    }

      

      

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

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

注意:

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