C#关于接收到的JSON多重结构的反序列化问题

2025-02-23 04:33:48
推荐回答(3个)
回答1:

JavaSerializer反序列化一个不知其类型的对象时,每一个属性的值都只可能是两种类型之一:Dictionary和 Array,其中被反序列化为Array的值在Json中本就是的数组。你的代码中没有考虑这一点所以异常了,多判断一下类型即可。


此外我还写了个简单的辅助类,应该能省去你一层层foreach的麻烦。该辅助类做了一点点优化,区分处理了字典和数组,不再需要遍历字典的key。


使用时把要访问的属性的”全路径“填进去就好,数组成员使用[ ]形式。如果指向不存在的属性则返回null。


例 var result = NonTypeObjectReader.GetValue(obj, "prop.children[0].innerProp"


    class NonTypeObjectReader
    {
        public static object GetValue(object obj, string expression)
        {
            var stack = GetExpQueue(expression);
            if (stack.Count > 0)
            {
                return GetValueInner(obj, stack);
            }
            return null;
        }
        private static object GetValueInner(object obj, Queue> stack)
        {
            if (stack.Count > 0)
            {
                var tup = stack.Dequeue();
                if (!tup.Item2)
                {
                    var dictObj = obj as IDictionary;
                    if (dictObj != null && dictObj.ContainsKey(tup.Item1))
                    {
                        return GetValueInner(dictObj[tup.Item1], stack);
                    }
                }
                else if (!(obj is IDictionary))
                {
                    var index = int.Parse(tup.Item1);
                    var arrObj = obj as Array;
                    if (arrObj != null && arrObj.Length > index)
                    {
                        return GetValueInner(arrObj.GetValue(index), stack);
                    }
                }
                return null;
            }
            return obj;
        }
        private static Queue> GetExpQueue(string expression)
        {
            var rtnStack = new Queue>();
            StringBuilder propName = new StringBuilder();
            var nextSaveIsIndex = false;
            for (var cursor = 0; cursor < expression.Length; cursor++)
            {
                var ch = expression[cursor];
                if (ch != '.' && ch != '[' && ch != ']')
                {
                    propName.Append(ch);
                }
                else if (propName.Length > 0)
                {
                    rtnStack.Enqueue(new Tuple(propName.ToString(), nextSaveIsIndex));
                    propName.Clear();
                    nextSaveIsIndex = ch == '[';
                }
            }
            if (propName.Length > 0)
            {
                rtnStack.Enqueue(new Tuple(propName.ToString(), false));
            }
            return rtnStack;
        }
    }


测试代码:

    var serializer = new JavaScriptSerializer();
    var rawObj = new
    {
        Prop1 = 1,
        Prop2 = "hello",
        Children = new[]
        {
            new
            {
                InnerProp = "1",
                Sub = new object[]{"string",2016}
            },
            new 
            {
                InnerProp="2",
                Sub = new object[]{DateTime.Now,2.5}
            }
        }
    };
    var jsonStr = serializer.Serialize(rawObj);
    var obj = serializer.DeserializeObject(jsonStr);
    var value = NonTypeObjectReader.GetValue(obj, "Children[0].Sub[1]");
    Debug.Assert(value is int && (int)value == 2016);

回答2:

直接用烦序列化类,不要自己去写,实在子节点深了 用正则截取, 或截取后反序列化

回答3:

运行的时候鼠标放在_b上面,看究竟是什么类型。