Search code examples
c#jsonloopsjson.netjson-deserialization

Iterate Through JSON Array in C#


I'm trying to figure out how to loop through some JSON data to insert it into a DataGrid, to serve as an event log. However trying to parse JSON is giving me a headache.

I'm trying to use JSON.NET by Newtonsoft.

The JSON string looks something like this;

{
    "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
        }
    }]}
}

I've been trying to do something like this;

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

I've also tried some other methods like using lists, but I simply can't get it to work and I keep getting a RuntimeBinderException. I've been stuck at this for so long now that I'm starting to consider to just use regex as this seems to be more work than it's worth.

What am I missing and/or misunderstanding here? :(


Solution

  •    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;
    

    A better (easier to use) version using dynamic.