C # JSON.NET – десериализация ответа, использующего необычную структуру данных

У меня возникли проблемы с выяснением чистого (максимально возможного) способа десериализации данных JSON в определенном формате. Я хочу десериализовать данные на строго типизированные classы объектов данных, довольно гибкие в отношении особенностей этого. Вот пример того, как выглядят данные:

{ "timestamp": 1473730993, "total_players": 945, "max_score": 8961474, "players": { "Player1Username": [ 121, "somestring", 679900, 5, 4497, "anotherString", "thirdString", "fourthString", 123, 22, "YetAnotherString"], "Player2Username": [ 886, "stillAstring", 1677, 1, 9876, "alwaysAstring", "thirdString", "fourthString", 876, 77, "string"] } } 

Конкретные детали, о которых я не уверен, таковы:

  1. Будет ли сбор игроков рассматриваться как словарь? Имя пользователя может служить ключом, но значение меня отбрасывает, поскольку это будет смешанная коллекция значений строк и целых чисел.
  2. Игрок состоит исключительно из неназванных значений. Я почти всегда работал с данными JSON, которые назвали свойства и значения (например, timestamp, total_players и т. Д. На самом верху)

Скажем, у меня class высшего уровня:

 public class ScoreboardResults { public int timestamp { get; set; } public int total_players { get; set; } public int max_score { get; set; } public List players { get; set; } } 

Что бы выглядел объект Player, учитывая, что он в основном является ключом / значением с именем пользователя, служащим в качестве ключа, а значением является коллекция смешанных целых чисел и строк? Данные для каждого элемента игрока всегда находятся в одном порядке, поэтому я знаю, что первым значением в коллекции является их UniqueID, второе значение – описание игрока и т. Д. Я бы хотел, чтобы class игрока был примерно таким:

 public class Player { public string Username { get; set; } public int UniqueID { get; set; } public string PlayerDescription { get; set; } .... .... .... Following this pattern for all of the values in each player element .... .... } 

Я уверен, что это довольно простая вещь, использующая JSON.NET, поэтому я хотел избежать любых идей, которые я имел о том, как это сделать. То, что я придумал, было бы не изящным и, вероятно, ошибкой, подверженной некоторой степени во время процесса сериализации.

РЕДАКТИРОВАТЬ

Вот classы, которые генерируются при использовании прошлого в качестве classов JSON, как предложено snow_FFFFFF :

 public class Rootobject { public int timestamp { get; set; } public int total_players { get; set; } public int max_score { get; set; } public Players players { get; set; } } public class Players { public object[] Player1Username { get; set; } public object[] Player2Username { get; set; } } 

Мне непонятно, как я десериализую данные JSON в элементе «игроки» как List с именем Player1Username, являющимся простым строковым свойством объекта Player. Что касается набора смешанных строк и целых чисел, я уверен, что я могу без проблем получить их в отдельных свойствах объекта Player.

Конвертер от десериализации JSON в Visual Basic .NET должен делать то, что вам нужно, соответствующим образом переводится с VB.NET на c #:

 public class ObjectToArrayConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(T) == objectType; } static bool ShouldSkip(JsonProperty property) { return property.Ignored || !property.Readable || !property.Writable; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var type = value.GetType(); var contract = serializer.ContractResolver.ResolveContract(type) as JsonObjectContract; if (contract == null) throw new JsonSerializationException("invalid type " + type.FullName); var list = contract.Properties.Where(p => !ShouldSkip(p)).Select(p => p.ValueProvider.GetValue(value)); serializer.Serialize(writer, list); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var token = JArray.Load(reader); var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract; if (contract == null) throw new JsonSerializationException("invalid type " + objectType.FullName); var value = existingValue ?? contract.DefaultCreator(); foreach (var pair in contract.Properties.Where(p => !ShouldSkip(p)).Zip(token, (p, v) => new { Value = v, Property = p })) { var propertyValue = pair.Value.ToObject(pair.Property.PropertyType, serializer); pair.Property.ValueProvider.SetValue(value, propertyValue); } return value; } } 

Затем добавьте конвертер в свой class Player и укажите порядок каждого свойства с помощью JsonPropertyAttribute.Order :

 [JsonConverter(typeof(ObjectToArrayConverter))] public class Player { [JsonProperty(Order = 1)] public int UniqueID { get; set; } [JsonProperty(Order = 2)] public string PlayerDescription { get; set; } // Other fields as required. } 

Затем, наконец, объявите свой корневой объект следующим образом:

 public class ScoreboardResults { public int timestamp { get; set; } public int total_players { get; set; } public int max_score { get; set; } public Dictionary players { get; set; } } 

Обратите внимание, что я переместил Username из classа Player и в словарь в качестве ключа.

Хорошим способом начать работу было бы позволить визуальной студии генерировать ваш class на основе JSON. Откройте пустой файл classа и перейдите к EDIT -> PASTE SPECIAL -> PASTE JSON as CLASSES.

Это приведет к созданию файла с необходимыми classами для сериализации / десериализации вашего JSON.

Попробуй это

Создайте class, как показано ниже.

Примечание. Вы можете использовать опцию «Вставить специальные» в visual studio для создания всех classов, связанных с JSON

Изменить -> Специальная вставка -> Вставить Json As Classes

он создаст все classы, связанные с JSON

Примечание: обратитесь к этому, я уже отвечаю подобным образом.

  • Избегайте сериализации jacksonа на непривлекательных ленивых объектах
  • Как сериализовать Java-примитивы с помощью Jersey REST
  • Заставить JSON.NET включать миллисекунды при сериализации DateTime (даже если компонент ms равен нулю)
  • Добавление к ObjectOutputStream
  • Сохранение / загрузка данных в Unity
  • jackson не десериализует общий список, который он сериализовал
  • Может ли Json.NET сериализовать / десериализовать в / из streamа?
  • Рекомендации по сериализации DateTime в .NET 3.5
  • «Тип не ожидается», используя DataContractSerializer - но это просто class, не смешные вещи?
  • Использовать имя classа в качестве корневого ключа для сериализации JSON Jackson
  • Сериализация OpenCV Mat_
  • Давайте будем гением компьютера.