Джексон запускает десериализацию на два уровня ниже

#java #jackson

#java #джексон

Вопрос:

У меня есть неуклюже сконструированный файл json, подобный этому:

 {
"clientByClientId" : {
  "123" : {
    "clientId" : "123"
     "moreFields" : "moreData"
   }
  "456" : {
    "clientId" : "456"
     "moreFields" : "moreData"
   }
 }
}
  

Как вы можете видеть, два верхних уровня этого json являются излишними. Каков наилучший способ десериализации этого в коллекцию Client объектов? Я попытался использовать онлайн-json для pojo tools, но в итоге они сгенерировали классы с именами «123» и «456». В идеале я хотел бы использовать Jackson, но я открыт для других решений.

Комментарии:

1. Единственный недостаток, который я вижу в вашей строке json, — это отсутствие запятых. Можете ли вы дважды проверить, расставив правильные запятые?

Ответ №1:

Небольшое примечание: ваш JSON неверно сформирован, так как в нем не хватает нескольких запятых. Как только они будут добавлены, это сработает для вас.

Прежде всего, вам понадобится класс для представления Client :

 public class Client {
    private final int clientId;
    private final String moreFields;

    @JsonCreator
    public Client(@JsonProperty("clientId") int clientId, 
                  @JsonProperty("moreFields") String moreFields) {
        this.clientId = clientId;
        this.moreFields = moreFields;
    }

    @Override
    public String toString() {
        return "Client[clientId="   clientId   ", moreFields="   moreFields   "]";
    }
}
  

Теперь вам просто нужно создать свою ObjectMapper и выполнить итерацию по элементам вашей clientByClientId карты, что можно сделать с помощью следующего:

 ObjectMapper objectMapper = new ObjectMapper();
JsonNode node = objectMapper.readTree(json).get("clientByClientId");
Map<Integer, Client> clientMap = objectMapper.readValue(node.traverse(),
        new TypeReference<Map<Integer, Client>>() {});
System.out.println(clientMap.values());
  

Вывод этого кода:

 [Client[clientId=123, moreFields=moreData], Client[clientId=456, moreFields=moreData]]
  

Комментарии:

1. Это идеально, спасибо! И да, моя ошибка с запятыми — слишком много работы с yaml испортило меня.

Ответ №2:

Я думаю, что что-то подобное должно сработать:

    public class Body {
    public ClientByClientId clientByClientId;
}

public class ClientByClientId {
    public Map<String, Client> clientMap;
}

public class Client {
    int clientId;
    String moreFields;
}
  

Это должно поместить ваши идентификаторы верхнего уровня в качестве ключа на карте.