Разбор JSON в Map <String, Entity> с помощью FlexJSON - PullRequest
1 голос
/ 02 ноября 2010

Я пытаюсь проанализировать структуру JSON, похожую на эту:

    {
 "cars": {
  "112": {
   "make": "Cadillac",
   "model": "Eldorado",
   "year": "1998"
  },
  "642": {
   "make": "Cadillac",
   "model": "Eldorado",
   "year": "1990"
  },
  "9242": {
   "make": "Cadillac",
   "model": "Eldorado",
   "year": "2001"
  }
 }}

У меня есть класс CarEntity, определенный с помощью makeName, модель, атрибуты года, определенные и доступные через сеттеры / получатели.

Я пытаюсь десериализовать этот JSON следующим образом:

    Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String, CarEntity>>()
   .use("cars.values", Map.class)
   .deserialize(json);

, и он не работает :( Он десериализует его, но не в Map<String, CarEntity>, а скорее в глубокую Карту (что-то вроде Map<String, Map<String, Map<String, String>>>)

Что я делаю не так?

Ответы [ 3 ]

2 голосов
/ 02 ноября 2010

Вы проблема в том, что у вашего json две карты. Тот, который содержит ключ 'cars', и тот, который содержит фактическое CarEntity. К сожалению, вы не можете ссылаться на один ключ на карте и назначать типы только для этого ключа в настоящее время. Обычно настройка типов для значений для коллекций относится ко всем значениям в коллекции. Вам не нужно указывать типы для первой карты, которая содержит ключ «cars», так как она будет десериализована по умолчанию.

Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String,Map<String, CarEntity>>>()
    .use("values.values", CarEntity.class )
    .deserialize(json).get("cars");

Путь 'values.values' относится к значениям внешней карты, после чего все следующие значения карты проходят все экземпляры CarEntity.

Я рассмотрел изменение выражений пути, чтобы сделать его более выразительным, позволяя вам ориентироваться на одно значение в коллекции, но это увеличивает накладные расходы при их оценке и обратной совместимости - это проблема.

1 голос
/ 02 ноября 2010

Скорее всего, вас укусила Java Type Erasure: соответствующая библиотека JSON не знает, какой тип вам нужен; все, что он видит, эквивалентно карте. Поэтому вы должны как минимум указать тип значения. Надеюсь, в документации FlexJSON указано, как.

В качестве альтернативы вы можете иметь возможность подкласса HashMap в свой собственный тип (MyEntityMap расширяет HashMap), поскольку тогда информация о типе может быть выведена из универсального супертипа; и передача MyEntityMap.class даст информацию о типе, которую может использовать большинство библиотек JSON (по крайней мере, Джексон и GSON).

Если они не работают, библиотеки Jackson и GSON могут легко справиться с этим вариантом использования; оба имеют методы для определения универсальных типов для десериализации.

0 голосов
/ 02 ноября 2010

Просто добавьте еще один вызов к get("cars"), например:

Map<String, CarEntity> deserialized = new JSONDeserializer<Map<String, CarEntity>>()
   .use("cars.values", Map.class)
   .deserialize(json).get("cars");

Строка jSon, вероятно, была сериализована из переменной cars, напечатанной как Map<String, CarEntity>

...