C# десериализация JSON без пользовательского класса в словарь или таблицу данных - PullRequest
0 голосов
/ 22 января 2020

из API я получаю json примерно так:

66 результатов игрока с 31 атрибутом, содержащим отдельные значения или массив значений.

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

И я хотел узнать, есть ли способ десериализации коллекции игроков в словарь или лучше DataTable со всеми 31 атрибутами без пользовательского класса игрока или доступ к каждому атрибуту индивидуально ?

Пока я пытался доступ к списку игроков:

        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());
                }
            }
        }

, который возвращает

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

Я представляю что-то вроде:

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

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

Ответ не может быть, что я должен сделать пользовательский класс игрока, а затем использовать его?

Открыть для любого совета. Спасибо.

Ответы [ 3 ]

1 голос
/ 22 января 2020

Это однострочный код для получения идентификатора игрока и имени игрока на List или 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);
1 голос
/ 22 января 2020

Вы можете использовать Newtonsoft. Json .Linq и получить требуемый результат, как показано ниже:

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

или, если вам нужен словарь, используйте ниже:

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

Если вы хотите отобразить все свойства игроков, вам нужно запустить l oop что-то вроде ниже:

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);
    }
}

Если вы хотите преобразовать в DataTable из списка игроков, то вы можете сделать что-то вроде ниже:

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);
}

Скрипач можно найти здесь .

1 голос
/ 22 января 2020

Вы можете выполнить синтаксический анализ IEnumerable<string> следующим образом:

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

Аналогичный подход будет работать для Dictionary с использованием ToDictionary вместо Select, но это зависит на то, что вы считаете ключом и значением.

...