2013-03-25 5 views
2

Я вызываю внешний веб-сервис, чтобы получить объект как json. Этот объект имеет свойство «значение», которое иногда является строкой, а иногда и массивом строк.Свойства java и json jackson - разные типы во время выполнения

public class MyClass { 

    // ... other variables 

    private String value; 

    public String getValue() { 
     return value; 
    } 

    @JsonProperty("value") 
    public void setValue(String value) { 
     this.value = value; 
    } 
} 

В настоящее время я получаю ошибку org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token жалуясь этой области. Мне было интересно, может ли кто-нибудь дать мне подсказку о том, что является правильным способом определения value в моем классе.

Это часть образца JSON, что мне приходится иметь дело с:

{ 
     "id": 12016907001, 
     "type": "Create", 
     "value": "normal", 
     "field_name": "priority" 
    }, 
    { 
     "id": 12016907011, 
     "type": "Create", 
     "value": [ 
     "sample", 
     "another" 
     ], 
     "field_name": "tags" 
    } 

Спасибо.

- EDIT

Я изменил тип значения в Object и решить мою проблему. Тем не менее, мне все еще интересно, есть ли лучший способ справиться с этим делом.

+0

Есть ли у вас какой-либо контроль над внешней веб-службой? –

+0

Не к сожалению – Abbas

ответ

8

Простой хак бы включить DeserializationFeature#ACCEPT_SINGLE_VALUE_AS_ARRAY, а затем использовать ответ Даниила. Если веб-служба возвращает строку, Джексон превратит ее в одноэлементную коллекцию.

EDIT:

Если вы не можете обновить Джексон 1.8 или выше, чтобы использовать эту функцию, вы могли бы сделать что-то вроде:

private Collection<String> value; 

public Collection<String> getValue() { 
    return value; 
} 

public void setValue(Object value) { 
    if (value instanceof Collection) { 
     this.value = (Collection<String>) value; 
    } else { 
     this.value = Arrays.asList((String) value); 
    } 
} 
+0

Это решение кажется очень интересным, но я использую 'org.codehaus.jackson.map.DeserializationConfig' не' com.fasterxml.jackson.databind.DeserializationFeature', и у него нет этой конфигурации! – Abbas

+1

Ну, меняя тип «значение» на объект, решил мою проблему. Однако, я думаю, ваше решение выглядит как наилучшее решение, и поэтому я принимаю его как ответ. Благодаря! – Abbas

+2

Эта опция находится в Jackson 1.8.0+, поэтому, если вы можете перейти к этой версии или выше, вы можете ее использовать. – HiJon89

0

Значение - массив, поэтому его нельзя преобразовать в строку.

Ты Java класс должен быть чем-то вроде следующего:

class MyClass 
{ 
    public int id; 
    public String type; 
    public Collection<String> value; 
    public String field_name; 
} 

Я использую открытые поля, например (это будет работать нормально).

+1

Это не отвечает на вопрос OP. Внешняя служба не имеет последовательного определения для поля 'value'. Иногда это массив, а иногда это просто строка. –

0

Вы можете использовать JsonNode как тип для вашей ценности. Впоследствии вы можете обработать свое значение в зависимости от возвращаемых значений isArray() (или isValueNode()). Я думаю, что JsonNodes - это самый удобный способ обработки raw JSON, потому что они предлагают широкую функциональность, помимо тех простых проверок.

if (value.isArray()) { 

    // process your array 

} else { 

    // process your string 

} 
Смежные вопросы