zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    ClassLoader机制:一个类何时会被虚拟机初始化?
    单例模式(含多线程处理)
    代理模式
    Java反射机制深度剖析
    python3.8、3.9安装
    日常随手记
    redux源码阅读之compose,applyMiddleware
    Chrome字体变粗
    JavaScript遍历树结构
    JavaScript 通过队列实现异步流控制
  • 原文地址:https://www.cnblogs.com/anonymous5L/p/json_decode_deep.html
Copyright © 2011-2022 走看看