C#深入解析Json格式內容


繼上一篇《淺談C#手動解析Json格式內容》我又來分析加入了一些功能讓 這個解析類更實用

本章節最會開放我最終制作成功的Anonymous.Json.dll這個解析庫 需要的拿走~

功能繼上一篇增加了許多上一篇只是講述了  解析的步驟但是 至於一些擴展的功能卻沒有涉及

本文將繼續講解

1.如何將json轉換為一個類或者結構 甚至屬性

2.如何將一個類或者結構甚至屬性轉換為json

就這兩點就已經很頭疼了 誒 廢話不多說進入正題

 

上一篇一直有個很神秘的JsonObject沒有講解 現在先來揭開JsonObject的神秘面紗

internal bool _isArray = false;

/// <summary>
/// 是否為json array類型
/// </summary>
public bool IsArray
{
    get { return _isArray; }
}

internal bool _isString = false;

/// <summary>
/// 是否為json string類型
/// </summary>
public bool IsString
{
    get { return _isString; }
}

internal bool _isBool = false;

/// <summary>
/// 是否為json bool類型
/// </summary>
public bool IsBool
{
    get { return _isBool; }
}

internal bool _isObject = false;

/// <summary>
/// 是否為json object類型
/// </summary>
public bool IsObject
{
    get { return _isObject; }
}

internal bool _isChar = false;

/// <summary>
/// 是否為json char類型
/// </summary>
public bool IsChar
{
    get { return _isChar; }
}

internal bool _isInt;

/// <summary>
/// 是否為json 整數型
/// </summary>
public bool IsInt
{
    get { return _isInt; }
}

internal bool _isLong;

/// <summary>
/// 是否為json 長整數型
/// </summary>
public bool IsLong
{
    get { return _isLong; }
}

internal bool _isDouble;

/// <summary>
/// 是否為json 浮點型
/// </summary>
public bool IsDouble
{
    get { return _isDouble; }
}

internal bool _isNull = false;

/// <summary>
/// 是否為json null
/// </summary>
public bool IsNull
{
    get { return _isNull; }
}

/// <summary>
/// 將object轉換為JsonObject
/// </summary>
/// <param name="obj"></param>
public JsonObject(object obj)
{
    ConvertToJsonObject(this, obj);
}

/// <summary>
/// 定義一個任意類型的隱式轉換
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static implicit operator JsonObject(string obj)
{
    return ImplicitConvert(obj);
}
public static implicit operator JsonObject(int obj)
{
    return ImplicitConvert(obj);
}
public static implicit operator JsonObject(double obj)
{
    return ImplicitConvert(obj);
}
public static implicit operator JsonObject(float obj)
{
    return ImplicitConvert(obj);
}
public static implicit operator JsonObject(long obj)
{
    return ImplicitConvert(obj);
}
public static implicit operator JsonObject(decimal obj)
{
    return ImplicitConvert(obj);
}
private static JsonObject ImplicitConvert(object convert)
{
    JsonObject obj = new JsonObject();
    obj.ValueConvertToJsonObject(convert.ToString(), false);
    return obj;
}
/// <summary>
/// 轉換形態
/// </summary>
/// <param name="parent"></param>
/// <param name="sourceObj"></param>
/// <returns>如果是基本類型返回false直接進行設置</returns>
private bool ConvertToJsonObject(JsonObject parent, object sourceObj)
{
    if (sourceObj == null)
        return false;
    Type t = sourceObj.GetType();
    if (t.IsGenericType)
    {
        Type ctorType = t.GetGenericTypeDefinition();
        if (ctorType == typeof(List<>))
        {
            parent._isArray = true;
            parent._sourceObj = new List<JsonObject>();
            int count = (int)t.GetProperty("Count").GetValue(sourceObj, null);
            MethodInfo get = t.GetMethod("get_Item");
            for (int i = 0; i < count; i++)
            {
                object value = get.Invoke(sourceObj, new object[] { i });
                JsonObject innerObj = new JsonObject();
                if (!ConvertToJsonObject(innerObj, value))
                {
                    innerObj.ValueConvertToJsonObject(value.ToString(), false);
                }
                parent.add(innerObj);
            }
        }
        else if (ctorType == typeof(Dictionary<,>))
        {
            parent._isObject = true;
            parent._sourceObj = new Dictionary<string, JsonObject>();
            int count = (int)t.GetProperty("Count").GetValue(sourceObj, null);
            object kv_entity = t.GetMethod("GetEnumerator").Invoke(sourceObj, null);
            Type entityType = kv_entity.GetType();
            for (int i = 0; i < count; i++)
            {
                bool mNext = (bool)entityType.GetMethod("MoveNext").Invoke(kv_entity, null);
                if (mNext)
                {
                    object current = entityType.GetProperty("Current").GetValue(kv_entity, null);
                    Type currentType = current.GetType();
                    object key = currentType.GetProperty("Key").GetValue(current, null);
                    object value = currentType.GetProperty("Value").GetValue(current, null);
                    if (!(key is string))
                        throw new Exception("json規范格式不正確 Dictionary起始key應為string類型");
                    JsonObject innerObj = new JsonObject();
                    innerObj._key = key.ToString();
                    if (!ConvertToJsonObject(innerObj, value))
                    {
                        innerObj.ValueConvertToJsonObject(value.ToString(), false);
                    }
                    parent.add(innerObj);
                }
            }
        }
        else
        {
            throw new Exception("不支持的泛型操作");
        }
        return true;
    }
    else if (t.IsArray)
    {
        parent._isArray = true;
        parent._sourceObj = new List<JsonObject>();

        int rank = t.GetArrayRank();
        if (rank > 1)
        {
            throw new Exception("暫不支持超過1維的數組");
        }
        else
        {
            int length_info = Convert.ToInt32(t.GetProperty("Length").GetValue(sourceObj, null));
            for (int i = 0; i < length_info; i++)
            {
                object innerObj = t.GetMethod("GetValue", new Type[] { typeof(int) }).Invoke(sourceObj, new object[] { i });
                JsonObject obj = new JsonObject();
                if (!ConvertToJsonObject(obj, innerObj))
                {
                    obj.ValueConvertToJsonObject(innerObj.ToString(), false);
                }
                parent.add(obj);
            }
        }
        return true;
    }
    else if ((t.IsValueType && !t.IsPrimitive) || (t.IsClass && !(sourceObj is string)))
    {
        parent._isObject = true;
        parent._sourceObj = new Dictionary<string, JsonObject>();
        PropertyInfo[] infos = t.GetProperties(BindingFlags.Instance | BindingFlags.Public);
        foreach (PropertyInfo item in infos)
        {
            JsonObject innerObj = new JsonObject();
            innerObj._key = item.Name;
            object obj = item.GetValue(sourceObj, null);
            if (!ConvertToJsonObject(innerObj, obj))
            {
                innerObj.ValueConvertToJsonObject(obj == null ? "null" : obj.ToString(), false);
            }
            parent.add(innerObj);
        }
        return true;
    }
    else
    {
        parent.ValueConvertToJsonObject(sourceObj.ToString(), false);
        return false;
    }
}

public JsonObject() { }

/// <summary>
/// 如果為json object提取索引內容
/// </summary>
/// <param name="index">key</param>
/// <returns></returns>
public JsonObject this[string index]
{
    get
    {
        if (IsObject)
        {
            if (ContainsKey(index))
            {
                return dictionary()[index];
            }
            else
            {
                throw new Exception("不包含 key: " + index);
            }
        }
        else
        {
            throw new Exception("該對象不是一個json object類型請用IsObject進行驗證后操作");
        }
    }
    set
    {
        if (IsObject)
        {
            if (value is JsonObject)
            {
                dictionary()[index] = value;
            }
            else
            {
                dictionary()[index] = new JsonObject(value);
            }
        }
        else
        {
            throw new Exception("該對象不是一個json object類型請用IsObject進行驗證后操作");
        }
    }
}

/// <summary>
/// 如果為json array提取索引內容
/// </summary>
/// <param name="index">index</param>
/// <returns></returns>
public JsonObject this[int index]
{
    get
    {
        if (IsArray)
        {
            if (index >= Count || index <= -1)
                throw new Exception("索引超出數組界限");
            return array()[index];
        }
        else
        {
            throw new Exception("該對象不是一個json array類型請用IsArray進行驗證后操作");
        }
    }
    set
    {
        if (IsArray)
        {
            if (value is JsonObject)
            {
                array()[index] = value;
            }
            else
            {
                array()[index] = new JsonObject(value);
            }
        }
        else
        {
            throw new Exception("該對象不是一個json array類型請用IsArray進行驗證后操作");
        }
    }
}

/// <summary>
/// 為json object 設置值如果存在則覆蓋
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Set(string key, object value)
{
    if (IsObject)
    {
        Dictionary<string, JsonObject> objs = dictionary();
        if (objs.ContainsKey(key))
        {
            if (value is JsonObject)
                objs[key] = (JsonObject)value;
            else
                objs[key] = new JsonObject(value);
        }
        else
        {
            if (value is JsonObject)
                objs.Add(key, (JsonObject)value);
            else
                objs.Add(key, new JsonObject(value));
        }
    }
    else
    {
        this._isArray = false;
        this._isBool = false;
        this._isChar = false;
        this._isDouble = false;
        this._isInt = false;
        this._isLong = false;
        this._isNull = false;
        this._isObject = true;
        this._isString = false;
        this._key = null;
        this._sourceObj = new Dictionary<string, JsonObject>();
    }
}

/// <summary>
/// 為json object 設置值如果存在則覆蓋
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Set<T>(string key, T value)
{
    Set(key, value);
}

/// <summary>
/// 為json array 添加值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add(object value)
{
    if (IsArray)
    {
        List<JsonObject> objs = array();
        if (value is JsonObject)
            objs.Add((JsonObject)value);
        else
            objs.Add(new JsonObject(value));
    }
    else
    {
        this._isArray = true;
        this._isBool = false;
        this._isChar = false;
        this._isDouble = false;
        this._isInt = false;
        this._isLong = false;
        this._isNull = false;
        this._isObject = false;
        this._isString = false;
        this._key = null;
        this._sourceObj = new List<JsonObject>();
    }
}

/// <summary>
/// 為json array 添加值
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void Add<T>(T value)
{
    Add(value);
}

/// <summary>
/// 刪除一個json object針對json object
/// </summary>
/// <param name="key"></param>
public void Remove(string key)
{
    if (this.IsObject)
    {
        dictionary().Remove(key);
    }
}

/// <summary>
/// 刪除一個json object針對json array
/// </summary>
/// <param name="key"></param>
public void Remove(int index)
{
    if (this.IsArray)
    {
        array().RemoveAt(index);
    }
}

/// <summary>
/// 檢測json object是否包含這個key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool ContainsKey(string key)
{
    return dictionary().ContainsKey(key);
}

/// <summary>
/// 獲得json object或者json array的總數量
/// </summary>
public int Count
{
    get
    {
        if (IsArray)
            return array().Count;
        else if (IsObject)
            return dictionary().Count;
        return -1;
    }
}

/// <summary>
/// 將json object原始數據轉換出去
/// </summary>
/// <returns></returns>
public override string ToString()
{
    return _sourceObj.ToString();
}

/// <summary>
/// json key
/// </summary>
internal string _key;
/// <summary>
/// 源可替代為任何數據
///     Dictionary<,>
///     List<>
///     String
///     Int
///     Double
///     Bool
////// </summary>
internal object _sourceObj;

/// <summary>
/// 將源數據轉換為json array
/// </summary>
/// <returns></returns>
internal List<JsonObject> array()
{
    if (_sourceObj is List<JsonObject>)
    {
        return (List<JsonObject>)_sourceObj;
    }
    else
    {
        return null;
    }
}

/// <summary>
/// 將源數據轉換為json dictionary
/// </summary>
/// <returns></returns>
internal Dictionary<string, JsonObject> dictionary()
{
    if (_sourceObj is Dictionary<string, JsonObject>)
    {
        return (Dictionary<string, JsonObject>)_sourceObj;
    }
    else
    {
        return null;
    }
}

/// <summary>
/// 封裝了個簡便的添加方法
/// </summary>
/// <param name="obj"></param>
internal void add(JsonObject obj)
{
    if (this.IsObject)
    {
        Dictionary<string, JsonObject> objs = dictionary();
        objs.Add(obj._key, obj);
    }
    else if (this.IsArray)
    {
        List<JsonObject> objs = array();
        objs.Add(obj);
    }
}

/// <summary>
/// 將json string 轉換為對應的實體object
/// </summary>
/// <param name="value"></param>
/// <param name="isFromComma">判斷是否來自逗號這樣好驗證格式不正常的string</param>
internal void ValueConvertToJsonObject(string value, bool isFromComma)
{
    //如果為string類型解析開始解析 json string
    if (value is string)
    {
        string str = value.ToString();
        bool isBaseType = false;
        if (str.IndexOf(".") != -1)
        {
            //嘗試解析double
            double out_d = -1;
            if (double.TryParse(str, out out_d))
            {
                isBaseType = true;
                this._isDouble = true;
                this._sourceObj = out_d;
            }
        }
        else
        {
            //嘗試解析長整數型
            long out_l = -1;
            if (long.TryParse(str, out out_l))
            {
                isBaseType = true;
                //如果小於長整數 換算為整數類型
                if (out_l <= int.MaxValue && out_l >= int.MinValue)
                {
                    this._isInt = true;
                    _sourceObj = (int)out_l;
                }
                else
                {
                    this._isLong = true;
                    _sourceObj = out_l;
                }
            }
        }
        if (!isBaseType)
        {
            if (str.ToLower().Equals("null"))
            {
                this._isNull = true;
            }
            else if (str.ToLower().Equals("true") || str.ToLower().Equals("false"))
            {
                this._isBool = true;
                this._sourceObj = bool.Parse(str.ToLower());
            }
            else
            {
                if (!isFromComma)
                {
                    this._isString = true;
                    int idx = str.IndexOf("\\u");
                    while (idx != -1)
                    {
                        string v = str.Substring(idx, 6);
                        string hex1 = v.Substring(2, 2);
                        string hex2 = v.Substring(4);
                        byte[] bytes = new byte[2] {
        Convert.ToByte(hex2,16),
        Convert.ToByte(hex1,16)
    };
                        str = str.Replace(v, Encoding.Unicode.GetString(bytes));
                        idx = str.IndexOf("\\u");
                    }
                    _sourceObj = str;
                }
                else
                {
                    throw new Exception("json字符串格式有誤 請加單引號或雙引號");
                }
            }
        }
    }
}

/// <summary>
/// 直接返回源數據
/// </summary>
/// <returns></returns>
public object ToObject()
{
    return _sourceObj;
}

/// <summary>
/// 轉換為json串
/// </summary>
/// <returns></returns>
public string ToJson()
{
    StringBuilder sb = new StringBuilder();
    if (IsObject)
    {
        sb.Append("{");
        Dictionary<string, JsonObject> objs = dictionary();
        List<string> keys = new List<string>(objs.Keys);
        int i;
        for (i = 0; i < keys.Count - 1; i++)
        {
            sb.Append("\"");
            sb.Append(keys[i]);
            sb.Append("\":");
            sb.Append(objs[keys[i]].ToJson());
            sb.Append(",");
        }
        sb.Append("\"");
        sb.Append(keys[i]);
        sb.Append("\":");
        sb.Append(objs[keys[i]].ToJson());
        sb.Append("}");
    }
    else if (IsArray)
    {
        sb.Append("[");
        List<JsonObject> objs = array();
        int i;
        for (i = 0; i < objs.Count - 1; i++)
        {
            sb.Append(objs[i].ToJson());
            sb.Append(",");
        }
        sb.Append(objs[i].ToJson());
        sb.Append("]");
    }
    else
    {
        if (!IsString)
        {
            if (IsBool)
            {
                sb.Append(((bool)_sourceObj) ? "true" : "false");
            }
            else if (IsNull)
            {
                sb.Append("null");
            }
            else
            {
                sb.Append(_sourceObj);
            }
        }
        else
        {
            sb.Append("\"");
            sb.Append(_sourceObj);
            sb.Append("\"");
        }
    }
    return sb.ToString();
}

/// <summary>
/// 將jsonobject轉換為實體object
///     有參的
/// </summary>
/// <typeparam name="T">實體object類型</typeparam>
/// <param name="ctor">構造參數</param>
/// <returns></returns>
public T ToObject<T>(params object[] ctor)
{
    object targetObj = null;
    if (this.IsObject || this.IsArray)
    {
        Type targetObjType = typeof(T);
        targetObj = CreateObject(targetObjType, ctor);
    }
    return (T)ConvertToObject(targetObj, this);
}

/// <summary>
/// 將jsonobject轉換為實體object
///     無參的
/// </summary>
/// <typeparam name="T">實體構造類型</typeparam>
/// <returns></returns>
public T ToObject<T>()
{
    return ToObject<T>(null);
}

private object ConvertToObject(object targetObj, JsonObject obj)
{
    Type targetType = null;
    if (targetObj != null)
        targetType = targetObj.GetType();
    //判斷下object
    if (obj.IsObject)
    {
        Dictionary<string, JsonObject> dictionarys = obj.dictionary();
        Dictionary<string, JsonObject>.Enumerator enumerator = dictionarys.GetEnumerator();
        while (enumerator.MoveNext())
        {
            string key = enumerator.Current.Key;
            JsonObject value = enumerator.Current.Value;
            PropertyInfo info = targetType.GetProperty(key, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
            if (targetType.IsGenericType)
            {
                if (targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
                {
                    object setInnerValue = null;
                    Type innerValueType = targetType.GetGenericArguments()[1];
                    setInnerValue = GetJsonObjectEntity(innerValueType, value);
                    setInnerValue = ConvertToObject(setInnerValue, value);
                    MethodInfo add_info = targetType.GetMethod("Add");
                    add_info.Invoke(targetObj, new object[] { key, setInnerValue });
                }
                else
                {
                    throw new Exception("\"" + targetType.Name + "\"屬性 \"" + key + "\"不是Dictionary泛型類型");
                }
            }
            else if (info != null)
            {
                object innerObj = info.GetValue(targetObj, null);
                if (innerObj == null)
                    innerObj = GetJsonObjectEntity(info.PropertyType, value);
                innerObj = ConvertToObject(innerObj, value);
                info.SetValue(targetObj, innerObj, null);
            }
            else
            {
                throw new Exception("\"" + targetType.Name + "\"類中找不到屬性 \"" + key + "\"無法完成轉換操作");
            }
        }
    }
    else if (obj.IsArray)
    {
        List<JsonObject> arrays = obj.array();
        for (int i = 0; i < arrays.Count; i++)
        {
            JsonObject item = arrays[i];
            if (targetType.IsGenericType)
            {
                Type[] types = targetType.GetGenericArguments();
                Type objType = types[0];
                object innerObj = GetJsonObjectEntity(objType, item);
                innerObj = ConvertToObject(innerObj, item);

                MethodInfo info = targetType.GetMethod("Add");
                info.Invoke(targetObj, new object[] { innerObj });
            }
            else if (targetType.IsArray)
            {
                object innerObj = GetJsonObjectEntity(targetType, item);
                innerObj = ConvertToObject(innerObj, item);

                MethodInfo info = targetType.GetMethod("SetValue", new Type[] { typeof(object), typeof(int) });
                info.Invoke(targetObj, new object[] { innerObj, i });
            }
        }
    }
    else
    {
        return obj._sourceObj;
    }
    return targetObj;
}

private object GetJsonObjectEntity(Type type, JsonObject value)
{
    object innerObj = null;
    if (value.IsObject && innerObj == null)
    {
        innerObj = CreateObject(type, null);
    }
    else if (value.IsArray)
    {
        if (innerObj == null)
        {
            if (type.IsGenericType)
            {
                innerObj = CreateObject(type, null);
            }
            else if (type.IsArray)
            {
                if (type.GetArrayRank() > 1)
                {
                    throw new Exception("暫不支持1維數組以上的數據類型");
                }

                innerObj = type.InvokeMember("Set", BindingFlags.CreateInstance, null, null, new object[] { value.Count });
            }
        }
    }
    return innerObj;
}

private object CreateObject(Type objType, params object[] ctor)
{
    try
    {
        object targetObj;
        if (ctor == null)
            targetObj = Activator.CreateInstance(objType);
        else
            targetObj = Activator.CreateInstance(objType, ctor);
        return targetObj;
    }
    catch (Exception ex)
    {
        throw new Exception("構造\"" + objType.FullName + "\"過程中出現異常  可能是類構造函數異常也可能是其他的異常 詳細參見InnerException", ex);
    }
}
View Code

恩 沒錯 這就是 這整個的JsonObject了 我基本加了隱式 轉換 get set訪問器刪除方法 增加方法 設置方法等等 還真是功能繁多啊

其中支持 Array數組的轉換  List<T>泛型的轉換 甚至 Dictionary<string,TV>的轉換  當然 字典類型的話key必須固定為string在復雜的json也不支持啊 嘿嘿

從上面的一堆Is***的屬性來看是為了判斷這個json object的類型  因為我定義了萬能類 也就是說這個類既代表object也代表array

有個特殊的構造函數 是 public JsonObject(object obj) 這是為了自己手動構造json 所創建的

這個類也沒什么好講解的核心的就是 相互轉換 還有ToJson這個方法 將這個類轉換為Json格式內容

 

忘貼使用方法了....

 這是為了 轉換過來 當然可以忽略

public class obj
{
    public string obj1 { get; set; }
    public obj2 obj2 { get; set; }
    public List<object[]> array { get; set; }
    public object null_test { get; set; }
}

public class obj2
{
    public string a1 { get; set; }
}

恩這才是貨真價實的轉換出來的代碼~

string json = @"{ 'obj1': 'asd', 'obj2': { 'a1': 'a1_test' }, 'array': [ [ 1, 2, 3, 4, 5, true, null ] ], 'null_test': null }";
JsonSerialization js = new JsonSerialization(json);
JsonObject jsonObj = js.Deserializa();
obj o = js.Deserializa<obj>();

//自定義構造json
JsonObject obj2 = new JsonObject();
obj2.Set("hello", "word");
obj2.Set("obj", o);
string str = obj2.ToJson();
//str = {"hello":"word","obj":{"obj1":"asd","obj2":{"a1":"a1_test"},"array":[[1,2,3,4,5,true]],"null_test":null}}

str = js.Serializa(obj2);
//str = {"hello":"word","obj":{"obj1":"asd","obj2":{"a1":"a1_test"},"array":[[1,2,3,4,5,true]],"null_test":null}}
string value = obj2["hello"].ToObject<string>();
//value = word;

 

當然我做的這個也不是很完美  如果有啥問題 可以及時和我溝通 一起來完善~

經過一位博友的點撥 做了IList的適配以及IDictionary的適配 還有一些特定的轉義字符的轉換~

QQ:1026926092 (ps:請注明來源否則不加)

完整類庫在這里: 下載地址

原帖地址: http://www.cnblogs.com/anonymous5L/p/json_decode_deep.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM