Джексон - Использование пользовательского PrettyPrinter с пользовательским JsonSerializer

Я использую Jackson v2.8.2 для сериализации JSON в файл.

Я создал собственный сериализатор и применил метод serialize для настройки вывода JSON по мере необходимости.

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

// myClass is the object I want to serialize

SimpleModule module = new SimpleModule();
module.addSerializer(MyClass.class, new MySerializer());

ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
mapper.registerModule(module);

try 
{
    mapper.writeValue(new File("json.txt"), myClass);
}

catch (JsonProcessingException e) 
{
    ...
}

Файл JSON создан, и содержимое выглядит хорошо.

Файл отформатирован в соответствии с DefaultPrettyPrinter, но я хочу использовать свой собственный PrettyPrinter, который я уже реализовал.

Как я могу это сделать?

Я пробовал следующее:

MyPrettyPrinter myPrettyPrinter = new MyPrettyPrinter();
mapper.writer(myPrettyPrinter);
mapper.writeValue(new File("json.txt"), myClass);

но это не вызывает мой пользовательский принтер.


person ksl    schedule 16.09.2016    source источник


Ответы (2)


Причина этого в том, что вызов Writer возвращает новый экземпляр ObjectWriter. На самом деле в ObjectMapper есть много фабричных методов, которые создают новые объекты для вашей работы.

Исходный код от ObjectMapper:

/**
     * Factory method for constructing {@link ObjectWriter} that will
     * serialize objects using specified pretty printer for indentation
     * (or if null, no pretty printer)
     */
    public ObjectWriter writer(PrettyPrinter pp) {
        if (pp == null) { // need to use a marker to indicate explicit disabling of pp
            pp = ObjectWriter.NULL_PRETTY_PRINTER;
        }
        return _newWriter(getSerializationConfig(), /*root type*/ null, pp);
    }

Итак, для вас это означает, что вы должны изменить свой код на:

MyPrettyPrinter myPrettyPrinter = new MyPrettyPrinter();
ObjectWriter myWriter = mapper.writer(myPrettyPrinter);
myWriter.writeValue(new File("json.txt"), myClass);

Обратите внимание на назначение myWriter, чтобы использовать правильный модуль записи при вызове writeValue

Вот пример использования ObjectMapper и красивого принтера по умолчанию:

public class OMTest {
    public static void main(String[] args) throws IOException {
        // test string
        String json = "  {\"a\" : \"b\", \"c\" : \"d\" } ";
        // mapper
        ObjectMapper mapper = new ObjectMapper();
        // json tree
        JsonNode tree = mapper.readTree(json);
        // the objectWriter assigned with a pretty printer
        ObjectWriter myWriter = mapper.writer(new DefaultPrettyPrinter());
        // print without pretty printer (using mapper)
        System.out.println(mapper.writeValueAsString(tree));
        System.out.println();
        // print with writer (using the pretty printer) 
        System.out.println(myWriter.writeValueAsString(tree));
    }
}

Это печатает:

{"a":"b","c":"d"}

{
  "a" : "b",
  "c" : "d"
}

Где первая строка использует преобразователь, а вторая печать использует писатель.

Ваше здоровье,

Артур

person pandaadb    schedule 16.09.2016
comment
Если я изменю код, как вы предлагаете, он не скомпилируется - Type mismatch: cannot convert from ObjectWriter to ObjectMapper. - person ksl; 16.09.2016
comment
@ksl ты прав. Прошу прощения, я обновил свой ответ. Вам нужно будет присвоить писателю переменную и использовать ее. - person pandaadb; 16.09.2016
comment
Спасибо, это работает. Также обратите внимание, что mapper.setDefaultPrettyPrinter(new MyPrettyPrinter()) тоже работает. Я наткнулся на это здесь - github.com/FasterXML/jackson-databind/issues/689< /а>. - person ksl; 16.09.2016

Иногда, в зависимости от того, чего вы хотите достичь, вы можете использовать DefaultPrettyPrinter и просто настройте Indenter следующим образом:

DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
Indenter indenter = new CustomSpaceIndenter();
printer.indentObjectsWith(indenter); // Indent JSON objects
printer.indentArraysWith(indenter);  // Indent JSON arrays

Есть связанный с этим вопрос: Сериализация JsonNode в очень специфический формат JSON в Джексоне

person cassiomolin    schedule 16.09.2016