2016-07-15 7 views
2

Я десериализую JSON в Map<Integer, String>.Как вы разбираете ключи объекта JSON как целые числа с Джексоном?

Но я получаю вышеуказанное classCastException, если пытаюсь назначить key примитиву int.

ObjectReader reader = new ObjectMapper().reader(Map.class); 
String patternMetadata = "{\"1\":\"name\", \"2\":\"phone\", \"3\":\"query\"}"; 
Map<Integer, String> map = reader.readValue(patternMetadata); 
System.out.println("map: " + map); 
for (Map.Entry<Integer, String> entry : map.entrySet()) 
{ 
    try 
    { 
     System.out.println("map: " + entry.getKey()); 
     int index = entry.getKey(); 
     System.out.println("map**: " + index); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

Я получаю эту java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer исключение на второй строке в try блоке.

Я даже попытался сменить int index = enty.getKey().intValue(). Но все же происходит одно и то же исключение.

P.S .: Я запускаю его в студии Android с использованием Robolectric framework.

+3

свойства JSON являются * никогда * 'int' значения; они всегда * строки. Я подозреваю, что вам нужно просто разобрать строку ... –

ответ

4

Эти ключи не являются целыми числами, они являются строками. Обратите внимание на котировки на них:

String patternMetadata = "{\"1\":\"name\", \"2\":\"phone\", \"3\":\"query\"}"; 
// ------------------------^^-^^-----------^^-^^------------^^-^^ 

Если это JSON (это, кажется), объектные имена свойств всегда строки.

Вам понадобится Map<String, String>, а затем вам необходимо разобрать ключи до int (при необходимости).

+0

Но как же она успешно десериализируется в Map ? – Heisenberg

+1

@Heisenberg: Это не так, он десериализуется в «Карта». Помните стирание стилей. :-) 'ObjectMapper' просто использует необработанную« карту ». Вторая строка вашего блока 'try' - это первое место в вашем коде, в котором компилятор вставил тип-специфический состав, поэтому он не работает. –

2

Jackson может десериализовать ключи в некоторые типы по умолчанию (или настраиваемые типы с некоторой дополнительной конфигурацией), если вы сообщите об этом.

С Map является общим типом, вам нужно использовать TypeReference, чтобы описать требуемую параметризацию.

reader устарел с 2.5. Вместо этого вы должны использовать readerFor. Постройте свой ObjectReader, предоставив соответствующий TypeReference с ключами Integer для Map. Тогда Джексон знает, что вы ожидаете значения Integer в качестве ключей к вашей карте.

ObjectReader reader = new ObjectMapper().readerFor(new TypeReference<Map<Integer, String>>() { 
}); 

Полный пример

ObjectReader reader = new ObjectMapper().readerFor(new TypeReference<Map<Integer, String>>() { 
}); 
String patternMetadata = "{\"1\":\"name\", \"2\":\"phone\", \"3\":\"query\"}"; 
Map<Integer, String> map = reader.readValue(patternMetadata); 
System.out.println("map: " + map); 
for (Map.Entry<Integer, String> entry : map.entrySet()) { 
    try { 
     System.out.println("map: " + entry.getKey()); 
     int index = entry.getKey(); 
     System.out.println("map**: " + index); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

печатает

map: {1=name, 2=phone, 3=query} 
map: 1 
map**: 1 
map: 2 
map**: 2 
map: 3 
map**: 3