Reputation: 166
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
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
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
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