Daniel Maurer
Daniel Maurer

Reputation: 166

C# deserialize JSON without custom class into Dictionary or DataTable

from an API I get a json like this:

66 results of an player with somewhat 31 attributes containing single values or an array of values.

{"api":
{"results":66,
    "players":
        [{
            "player_id":10,
            "player_name":"Gustavo Ferrareis",
            ... (some 31 stats)
            "shots":{
                    "total":13,
                    "on":2
                },
            ...
          },
            "player_id":21,
            ...
       }]
     }

And I wanted to know if there's a way to deserialize the collection of players into an Dictionary or better DataTable with all 31 attributes without a custom player class or accessing every attribute individually?

So far I tried accessing the players list by:

        var data = JObject.Parse(json);
        foreach (var field in data)
        {
            var data2 = JObject.Parse(field.Value.ToString());
            foreach (var field2 in data2)
            {
                if (field2.Key.ToString() == "players")
                {
                    dynamic array2 = JsonConvert.DeserializeObject(field2.Value.ToString());

                    foreach (var field3 in array2)
                        Console.WriteLine("Player_id: " + field3.player_id.ToString() + " - Player_name: " + field3.player_name.ToString());
                }
            }
        }

which returns

Player_id: 10 - Player_name: Gustavo Ferrareis
Player_id: 22 - Player_name: Getúlio
Player_id: 22 - Player_name: Getúlio

I imagine something like:

Dictionary<string, object> dict = new Dictionary<string, object>();

foreach (var player in array2)
    dict.Add(player.Key(), player.Value());

The answer can't be that I have to make an custom player class and then use that?

Open for any advice. Thank you.

Upvotes: 0

Views: 483

Answers (3)

sam
sam

Reputation: 1985

You can use Newtonsoft.Json.Linq and get the required result as shown below:

var jObject = JObject.Parse(jsonFromAPI)["api"];
var formattedPlayers = jObject["Players"].Children()
                .Select(p => $"Player_id: {p["player_id"]} - Player_name: {p["player_name"]}");

or if you wanted dictionary, then use below:

var playersDictionary = jObject["Players"].Children().Select(p => new {player_id = p["player_id"], player_name = p["player_name"]}).ToDictionary(x => x.player_id, v => v.player_name);

If you want to display all properties of Players, then you need to run loop something like below:

var allPlayerDetails = new List<Dictionary<string, object>>();
foreach (JObject player in jObject["Players"].Children())
{
    var playerDictionary = player.Properties()
        .ToDictionary<JProperty, string, object>(property => property.Name, property => property.Value);

    allPlayerDetails.Add(playerDictionary);
}

for (var index = 0; index < allPlayerDetails.Count; index++)
{
    var playerDictionary = allPlayerDetails[index];
    Console.WriteLine(Environment.NewLine);
    Console.WriteLine(string.Format("Printing Player# {0}", index));
    foreach (var d in playerDictionary)
    {
        Console.WriteLine(d.Key + " - " + d.Value);
    }
}

If you want to convert to DataTable from list of players, then you can do something like below:

DataTable dt = new DataTable();

foreach (var column in allPlayerDetails.SelectMany(p => p.Keys).Select(k => k.Trim()).Distinct())
{
    dt.Columns.Add(new DataColumn(column));
}

foreach (var details in allPlayerDetails)
{
    var dr = dt.NewRow();
    foreach (DataColumn dc in dt.Columns)
    {
        dr[dc.ColumnName] = details.ContainsKey(dc.ColumnName) ? details[dc.ColumnName] : null;
    }
    dt.Rows.Add(dr);
}

Fiddler can be found here.

Upvotes: 1

Krishna Varma
Krishna Varma

Reputation: 4260

Here is the single line code to get the playerid and playername to List or Dictionary

//To List
var resultToList = JObject.Parse(jsonstring)["api"]["players"]
                   .Select(p => (p["player_id"].ToString(), p["player_name"].ToString()))
                   .ToList();

//To Dictionary
var resultToDict = JObject.Parse(jsonstring)["api"]["players"]
                   .Select(p => (p["player_id"].ToString(), p["player_name"].ToString()))
                   .ToDictionary(x=>x.Item1, y=>y.Item2);

Upvotes: 1

Johnathan Barclay
Johnathan Barclay

Reputation: 20373

You could parse into IEnumerable<string> like this:

IEnumerable<string> = JObject.Parse(json)["players"]
    .Children()
    .Select(jo => $"Player_id: {jo["player_id"]} - Player_name: {jo["player_name"]});

A similar approach would work for Dictionary using ToDictionary instead of Select, but it depends on what you consider key and value.

Upvotes: 1

Related Questions