Динамический выбор требуемой информации в формате JSON
-
20-12-2019 - |
Вопрос
Мне нужно десериализовать некоторый JSON, но проблема в том, что все мои объекты JSON не имеют точно такого же формата.Вот пример JSON, который я должен десериализовать :
[
{
"Player_Name": "Zlatan Ibrahimovic",
"Country": "Sweeden",
"Other_Informations": {
"Information1": [
]
},
},
{
"Player_Name": "Pavel Nedved",
"Country": "Czech Republic",
"Personal_Honours":
{
"Ballon_DOr": "One",
},
"Other_Informations": {
"Information1": [
]
},
},
{
"Player_Name": "Zinedine Zidane",
"Country": "Sweeden",
"Other_Informations": {
"Information1": [
{
"name": "example",
}
]
},
}
]
Как вы можете видеть, некоторые поля отображаются только для некоторых объектов, например "Personal_Honours".Мне нужно десериализовать JSON в этот класс :
public class PlayerData
{
public string Name { get; set; }
public string BallonDor {get; set; }
public string Information1{ get; set; }
public string Country{ get; set; }
}
Я использую этот метод, который действительно длинный и блокирует мое приложение :(В этом примере я использую Json, который поступает из текстового файла, но обычно мне приходится делать запрос REST..)
StreamReader reader = File.OpenText("TextFile1.txt");
List<PlayerData> DataList;
dynamic value= JsonConvert
.DeserializeObject<dynamic>(reader.ReadToEnd());
DataList = new List<PlayerData>();
foreach (dynamic data in value)
{
if (data.Personal_Honours == null)
{
if (data.Other_Informations.Information1 == null)
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
});
}
else
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
Information1 = data.Informations.Information1
});
}
}
else
{
if (data.Other_Informations.Information1 == null)
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
BallonDor = data.Personal_Honours.Ballon_DOr
});
}
else
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
BallonDor = data.Personal_Honours.Ballon_DOr,
Information1 = data.Informations.Information1
});
}
}
}
Этот метод работает, но он неэффективен и блокирует мой пользовательский интерфейс.Как я могу создать новый объект "PlayerData" без использования всех этих операторов "else if"?
Спасибо!
P.s. :Этот вопрос отличается от этого Фильтровать информацию в формате JSon
РЕДАКТИРОВАТЬ :
Вот как я получил исключение RunTimeBinderExcepetion :
List<PlayerData> datalist = new List<PlayerData>();
foreach (dynamic pl in timeline)
{
datalist.Add(new PlayerData
{
Name = pl.Player_Name ,
Country = pl.Country ,
BallonDor = pl.Personal_Honours.Ballon_Dor,
Information1 = pl.Other_Informations.Information1.name
});
}
Решение
Вы получили исключение, потому что некоторые данные не имеют Personal_Honours
собственность, например.Затем вы попытались получить доступ Ballon_Dor
собственность от null
ссылка, которая запускает исключение.Этот способ будет работать для примера JSON, который вы опубликовали :
List<PlayerData> datalist = new List<PlayerData>();
foreach (dynamic pl in timeline)
{
//object initialization is done later just for the sake of easier debugging
//...so we can spot unexpected data which cause exception easily
var Name = pl.Player_Name;
var Country = pl.Country;
var BallonDor = pl.Personal_Honours != null ? pl.Personal_Honours.Ballon_Dor : null;
var Information1 = pl.Other_Informations.Information1.Count > 0 ?
pl.Other_Informations.Information1[0].name :
null;
datalist.Add(new PlayerData
{
Name = Name ,
Country = Country ,
BallonDor = BallonDor,
Information1 = Information1
});
}
...но описанный выше подход по-прежнему подвержен ошибкам в зависимости от того, насколько согласована имеющаяся у нас строка JSON.Более надежный подход, возможно, заключается в том, чтобы иметь классы моделей для сопоставления строки JSON, как предложено @L.B в комментарии.