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

posted @ 2014-11-04 23:08  5L丶  阅读(4356)  评论(4编辑  收藏  举报