Универсальный объект сериализации в Джексоне с Java - PullRequest
7 голосов
/ 14 февраля 2011

Я хотел бы прочитать в строке {"a": 1.0} как общий объект Java, сохраняя тот же формат строки. Однако при попытке Джексон автоматически меняет внутреннее представление на {a = 1}. Другими словами, как я могу получить следующий код для печати {"a": 1.0} вместо {a = 1}? Обратите внимание, что я должен читать это как Object (из-за других программных ограничений).

import org.codehaus.jackson.map.ObjectMapper;

public class Main {

    public static void main(String[] args) {
        try
    {
            ObjectMapper mapper = new ObjectMapper();
            Object myObject = mapper.readValue("{\"a\": 1.0}", Object.class);
            System.out.println(myObject.toString());            
    }
    catch (Exception e)
    {
        e.printStackTrace();
      System.err.println(e.getMessage()); 
    }
    }

}

Ответы [ 4 ]

7 голосов
/ 23 апреля 2011

Созданный объект будет картой (как и другие комментарии), поэтому его toString создает то, что вы видите, {a = 1}. Чтобы ваш код печатал что-то ближе к вашему входному значению, вам нужно использовать Джексона, чтобы записать его обратно с чем-то вроде:

System.out.println(mapper.writeValueAsString(myObject));

Это дает мне то, что, я полагаю, вы ищете:

{"a":1.0}

Другими словами, Джексон десериализовал вашу входную строку в произвольный объект Java. Когда вы вызываете toString для объекта, его собственный toString, конечно, используется. Это может написать объект как угодно, включая использование метода из Object. Чтобы воспроизвести входную строку, вы должны использовать Джексона для сериализации нашего объекта обратно.

3 голосов
/ 14 февраля 2011

Вам нужен существующий класс, который соответствует желаемой структуре json. Объект не такой класс. Вы по-прежнему можете ссылаться на него как Object, если это необходимо:

Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class);
2 голосов
/ 14 февраля 2011

Когда Джексону говорят связать JSON с Object.class, он делает именно это;но поскольку у него нет априорных знаний о том, что может быть в этом JSON (или какие классы можно использовать), он должен использовать большинство базовых типов Java: карты, списки, числа, логические значения и строки.Таким образом, любой объект JSON представлен картой;JSON Array by List и т. Д.

Если вам нужен пользовательский объект, вы должны указать его тип;или, при сериализации, включите включение явной информации о типе («обработка полиморфного типа»).Это добавит либо имя класса, либо имя типа, и может быть использовано для десериализации обратно до точного типа.

Для этого либо сам тип (либо один из его супертипов) должен использовать аннотацию @JsonTypeInfo;или, если это свойство объекта, @JsonTypeInfo для свойства (поле или метод).

2 голосов
/ 14 февраля 2011

Если вы используете отладчик, вы увидите, что тип возвращаемого объекта - LinkedHashMap.Итак, что вы видите, это вывод LinkedHashMap.toString().Джексон не может изменить это, поэтому вы можете либо привести его к карте и создать строку самостоятельно, либо запросить другой тип возврата, который сгенерирует для вас строку JSON:

if(myObject instanceof Map<?, ?>){
    final Map<?, ?> map = (Map<?, ?>) myObject;
    final StringBuilder sb = new StringBuilder("{");
    boolean first = true;
    for(final Entry<?, ?> entry : map.entrySet()){
        if(first){
            first = false;
        } else{
            sb.append(",");
        }
        sb.append("\n\t'")
            .append(entry.getKey())
            .append("':'")
            .append(entry.getValue())
            .append("'");
    }
    if(!first){
        sb.append("\n");
    }
    sb.append("}");
    System.out.println(sb.toString());

} else{
    System.out.println(myObject);
}

Вывод:

{
    'a':'1.0'
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...