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

我从其它网站获取信息,接收到一串JSON,我只想取其distance中的值,JavaScriptSerializerjss=newJavaScriptSerializer... 我从其它网站获取信息,接收到一串JSON,我只想取其distance中的值, JavaScriptSerializer jss=new JavaScriptSerializer();
Dictionary<string, object> ar = (Dictionary<string, object>)jss.DeserializeObject(str);
foreach (var _a in ar)
{
if (_a.Key == "result")
foreach (var _b in (Dictionary<string, object>)_a.Value)///此处断点显示的是 _a.Value count=4可以强类型转换
{
if (_b.Key == "routes")
{
foreach (var _c in (Dictionary<string, object>)_b.Value)//此处断点显示 _b.Value object[1] 这里转换失败,退出
{
foreach (var _d in (Dictionary<string, object>)_c.Value)
if (_d.Key == "distance")
str = Convert.ToString(_d.Value);
}
}
}
}
请教 foreach (var _c in (Dictionary<string, object>)_b.Value)这个地方要怎么修改?
展开
 我来答
makosharp
2016-08-07 · TA获得超过676个赞
知道小有建树答主
回答量:188
采纳率:100%
帮助的人:269万
展开全部

JavaSerializer反序列化一个不知其类型的对象时,每一个属性的值都只可能是两种类型之一:Dictionary<string,object>和 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<Tuple<string, bool>> stack)
        {
            if (stack.Count > 0)
            {
                var tup = stack.Dequeue();
                if (!tup.Item2)
                {
                    var dictObj = obj as IDictionary<string, object>;
                    if (dictObj != null && dictObj.ContainsKey(tup.Item1))
                    {
                        return GetValueInner(dictObj[tup.Item1], stack);
                    }
                }
                else if (!(obj is IDictionary<string, object>))
                {
                    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<Tuple<string, bool>> GetExpQueue(string expression)
        {
            var rtnStack = new Queue<Tuple<string, bool>>();
            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<string, bool>(propName.ToString(), nextSaveIsIndex));
                    propName.Clear();
                    nextSaveIsIndex = ch == '[';
                }
            }
            if (propName.Length > 0)
            {
                rtnStack.Enqueue(new Tuple<string, bool>(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);
腊妹香
2016-08-03 · TA获得超过114个赞
知道小有建树答主
回答量:116
采纳率:100%
帮助的人:44.3万
展开全部
直接用烦序列化类,不要自己去写,实在子节点深了 用正则截取, 或截取后反序列化
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
阳光的雷咩咩
2016-08-02 · TA获得超过1.4万个赞
知道大有可为答主
回答量:2.3万
采纳率:66%
帮助的人:7799万
展开全部
运行的时候鼠标放在_b上面,看究竟是什么类型。
追问
object类型,现在是用实体类做到了,但还是想不用实体类怎么达到这目的
追答
不知道你说的实体类指什么?
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式