Вы близко. Если вы определяете свой класс Toy
, как у вас есть в своем вопросе, вы можете deserialize в List<Dictionary<string, Toy>>
. Таким образом, каждая игрушка фактически представлена Dictionary
с одной записью в ней. Key
- название игрушки, а Value
- это информация Toy
.
Вот демо:
string json = @"
[ { ""kite"" : { ""supplier"" : ""ABC"",
""currency"" : ""GBP"",
""cost"" : ""7.98""
} },
{ ""puzzle"" : { ""supplier"" : ""DEF"",
""currency"" : ""USD"",
""cost"" : ""7.98""
} },
{ ""ball"" : { ""supplier"" : ""DEF"",
""currency"" : ""USD"",
""cost"" : ""5.49""
} }
]";
List<Dictionary<string, Toy>> list =
JsonConvert.DeserializeObject<List<Dictionary<string, Toy>>>(json);
foreach (Dictionary<string, Toy> dict in list)
{
KeyValuePair<string, Toy> kvp = dict.First();
Console.WriteLine("toy: " + kvp.Key);
Console.WriteLine("supplier: " + kvp.Value.Supplier);
Console.WriteLine("cost: " + kvp.Value.Cost + " (" + kvp.Value.Currency + ")");
Console.WriteLine();
}
Это выводит следующее:
toy: kite
supplier: ABC
cost: 7.98 (GBP)
toy: puzzle
supplier: DEF
cost: 7.98 (USD)
toy: ball
supplier: DEF
cost: 5.49 (USD)
Следует признать, что это решение является своего рода «неуклюжим», потому что было бы лучше иметь название игрушки включены в самом классе Toy
, а не вмешиваться Dictionary
, чтобы споткнуться. Есть два способа исправить это. Один из способов - добавить свойство Name
в класс Toy
, десериализовать в ту же структуру, что и показано выше, затем сделать небольшую постобработку, чтобы переместить имена из каждого Dictionary
в соответствующие Toy
, построив новый List<Toy>
в процессе , Второй способ сделать это - создать пользовательский JsonConverter
для обработки этого перевода во время десериализации. Я бы с удовольствием продемонстрировал любой из этих альтернативных подходов, если вы пожелаете. Просто дай мне знать. Если вам просто нужно быстро и грязно, тогда должен действовать вышеуказанный подход.
Альтернативный подход с использованием пользовательских JsonConverter
Этот подход немного «чище», потому что мы можем держать всю информацию Toy
вместе на одном строго типизированный объект и сохранить все логики десериализации отдельно, так что не загромождает основной код.
Прежде всего, мы должны изменить ваш класс Toy
, чтобы дать ему Name
.
class Toy
{
public string Name { get; set; }
public string Supplier { get; set; }
public string Currency { get; set; }
public decimal Cost { get; set; }
}
Далее мы создаем класс, который наследуется от JsonConverter
.
class ToyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// This lets JSON.Net know that this converter can handle Toy objects
return (objectType == typeof(Toy));
}
public override object ReadJson(JsonReader reader,
Type objectType, object existingValue, JsonSerializer serializer)
{
// load the toy JSON object into a JObject
JObject jo = JObject.Load(reader);
// get the first (and only) property of the object
JProperty prop = jo.Properties().First();
// deserialize the value of that property (which is another
// object containing supplier and cost info) into a Toy instance
Toy toy = prop.Value.ToObject<Toy>();
// get the name of the property and add it to the newly minted toy
toy.Name = prop.Name;
return toy;
}
public override void WriteJson(JsonWriter writer,
object value, JsonSerializer serializer)
{
// If you need to serialize Toys back into JSON, then you'll need
// to implement this method. We can skip it for now.
throw new NotImplementedException();
}
}
Чтобы использовать конвертер, нам просто нужно создать экземпляр этого и передать его в вызове DeserializeObject<T>()
. Теперь, когда у нас есть этот конвертер, мы можем десериализовать непосредственно в List<Toy>
, что намного более естественно.
List<Toy> toys = JsonConvert.DeserializeObject<List<Toy>>(json, new ToyConverter());
Доступ к данным о игрушках осуществляется прямолинейно.
foreach (Toy toy in toys)
{
Console.WriteLine("toy: " + toy.Name);
Console.WriteLine("supplier: " + toy.Supplier);
Console.WriteLine("cost: " + toy.Cost + " (" + toy.Currency + ")");
Console.WriteLine();
}
Вы заметите, что это дает точно такой же результат, как в предыдущем примере, но код намного чище.
Похоже, что это был бы словарь. Кайт, головоломка и мяч будут ключами. Значения были бы типом, если бы объект имел свойства поставщика, валюты и стоимости. Однако я не могу исследовать, как десериализовать это на данный момент. Однако я хотел бы изучить какой-то динамический объект и, возможно, перевести его в нечто более конкретное. –