在C#中迭代JSON数组

时间:2017-11-04 19:18:09

标签: c# json loops json.net json-deserialization

我试图弄清楚如何遍历一些JSON数据以将其插入到DataGrid中,以充当事件日志。然而,尝试解析JSON让我很头疼。

我试图使用Newtonsoft的JSON.NET。

JSON字符串看起来像这样;

{
    "result" : "ok",
    "response" : {
    "first" : 0,
    "count" : 190,
    "now" : 1509822169,
    "events" : [
    {
        "index" : 0,
        "time" : 1509815973,
        "name" : "SessionCreated",
        "attributes" : {}
    },
    {
        "index" : 1,
        "time" : 1509815973,
        "name" : "PlayerJoined",
        "refid" : 32896,
        "attributes" : {}
        "Name" : "Dealman",
        "SteamId" : "76561197986562417"
    },
    {
        "index" : 2,
        "time" : 1509815973,
        "name" : "Authenticated",
        "refid" : 32896,
        "attributes" : {}
    },
    {
        "index" : 3,
        "time" : 1509815973,
        "name" : "StateChanged",
        "attributes" : {}
        "PreviousState" : "None",
        "NewState" : "Lobby"
    },
    {
        "index" : 4,
        "time" : 1509815998,
        "name" : "PlayerChat",
        "refid" : 32896,
        "attributes" : {
            "Message" : "This is a message"
        }
    },
    {
        "index" : 5,
        "time" : 1509816030,
        "name" : "StateChanged",
        "attributes" : {}
        "PreviousState" : "Lobby",
        "NewState" : "Loading"
    },
    {
        "index" : 6,
        "time" : 1509816030,
        "name" : "SessionSetup",
        "attributes" : {}
        "GridSize" : 22,
        "MaxPlayers" : 22,
        "PracticeLength" : 0,
        "QualifyLength" : 15,
        "RaceLength" : 6,
        "Flags" : -1316224232,
        "TrackId" : -52972612,
        "GameMode" : -1958878043
    },
    {
        "index" : 7,
        "time" : 1509816030,
        "name" : "StageChanged",
        "attributes" : {
            "PreviousStage" : "Practice1",
            "NewStage" : "Qualifying1",
            "Length" : 15
        }
    },
    {
        "index" : 8,
        "time" : 1509816046,
        "name" : "StateChanged",
        "attributes" : {
            "PreviousState" : "Loading",
            "NewState" : "Race"
        }
    },
    {
        "index" : 9,
        "time" : 1509816046,
        "name" : "ParticipantCreated",
        "refid" : 32896,
        "participantid" : 0,
        "attributes" : {
            "Name" : "Dealman",
            "IsPlayer" : 1,
            "VehicleId" : 1764851930,
            "LiveryId" : 54
        }
    }]}
}

我一直试图做这样的事情;

dynamic jsonObj = JsonConvert.DeserializeObject(messageContent);
foreach(var item in jsonObj)
{
    Trace.WriteLine(item.result);
}

我还尝试了一些其他方法,例如使用列表,但我根本无法使其工作,并且我不断获得 RuntimeBinderException 。我已经坚持了很长时间,因为我开始考虑使用正则表达式,因为这似乎比它的价值更多。

我在这里错过了什么和/或误解了什么? :(

3 个答案:

答案 0 :(得分:1)

    var json = @"...";

    var obj = ToObject(json) as IDictionary<string, object>;
    var resp = obj["response"] as IDictionary<string, object>;
    var events = resp["events"];

    public static object ToObject(string json)
    {
        if (string.IsNullOrEmpty(json))
            return null;
        return ToObject(JToken.Parse(json));
    }

    private static object ToObject(JToken token)
    {
        switch (token.Type)
        {
            case JTokenType.Object:
                return token.Children<JProperty>()
                            .ToDictionary(prop => prop.Name,
                                          prop => ToObject(prop.Value),
                                          StringComparer.OrdinalIgnoreCase);

            case JTokenType.Array:
                return token.Select(ToObject).ToList();

            default:
                return ((JValue)token).Value;
        }
    }

json字符串转换为Dictionary,其中items是简单值,列表或嵌套字典。迭代词典比使用反射更容易。

顺便说一下,你的json中有一个错误 - 在“属性”之后缺少逗号:{}。此外,同时将“名称”和“名称”作为属性并不是一个好主意。

答案 1 :(得分:1)

您遇到的问题是因为result是一个不属于集合的顶级属性,因此尝试使用循环访问它并没有任何意义。这会按预期打印ok

using Newtonsoft.Json;
using System;
using System.IO;

namespace SO47114632Core
{
    class Program
    {
        static void Main(string[] args)
        {
            var content = File.ReadAllText("test.json");
            dynamic json = JsonConvert.DeserializeObject(content);
            Console.WriteLine(json.result);
        }
    }
}

我在项目的根文件夹中添加了test.json来自您问题的JSON,并在文件的属性中将Copy to Output Directory设置为Always

File Properties

答案 2 :(得分:1)

   public static ExpandoObject ToExpando(string json)
    {
        if (string.IsNullOrEmpty(json))
            return null;
        return (ExpandoObject)ToExpandoObject(JToken.Parse(json));
    }


    private static object ToExpandoObject(JToken token)
    {

        switch (token.Type)
        {
            case JTokenType.Object:
                var expando = new ExpandoObject();
                var expandoDic = (IDictionary<string, object>)expando;
                foreach(var prop in token.Children<JProperty>())
                    expandoDic.Add(prop.Name, ToExpandoObject(prop.Value));
                return expando;
            case JTokenType.Array:
                return token.Select(ToExpandoObject).ToList();

            default:
                return ((JValue)token).Value;
        }
    }

    var ebj = ToExpando(json);
    var name = (ebj as dynamic).response.events[1].name;

使用动态更好(更易于使用)的版本。