28

I am using Jackson and would like to pretty-print JSON such that each element in arrays goes to each line, like:

{
  "foo" : "bar",
  "blah" : [
    1,
    2,
    3
  ]
}

Setting SerializationFeature.INDENT_OUTPUT true only inserts newline characters for object fields, not array elements, printing the object in this way instead:

{
  "foo" : "bar",
  "blah" : [1, 2, 3]
}

Does anyone know how to achieve this? Thanks!

lyomi
  • 4,230
  • 6
  • 30
  • 39

6 Answers6

32

If you don't want to extend DefaultPrettyPrinter you can also just set the indentArraysWith property externally:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);

String json = objectMapper.writer(prettyPrinter).writeValueAsString(object);
Dan Dar3
  • 1,199
  • 13
  • 23
Stefan Haberl
  • 9,812
  • 7
  • 72
  • 81
  • 9
    Lf2SpacesIndenter is deprecated (and gone in newer versions); Use DefaultIndenter.SYSTEM_LINEFEED_INSTANCE – Jay Sep 17 '18 at 12:30
  • 1
    Worked for me with DefaultIndenter.SYSTEM_LINEFEED_INSTANCE. This answer provides an easier solution. – Abhijay Kumar Sep 11 '20 at 09:24
17

Thanks to the helpful hints, I was able to configure my ObjectMapper with desired indentation as follows:

private static class PrettyPrinter extends DefaultPrettyPrinter {
    public static final PrettyPrinter instance = new PrettyPrinter();

    public PrettyPrinter() {
        _arrayIndenter = Lf2SpacesIndenter.instance;
    }
}

private static class Factory extends JsonFactory {
    @Override
    protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException {
        return super._createGenerator(out, ctxt).setPrettyPrinter(PrettyPrinter.instance);
    }
}

{
    ObjectMapper mapper = new ObjectMapper(new Factory());
    mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
}
lyomi
  • 4,230
  • 6
  • 30
  • 39
12

You could extend the DefaultPrettyPrinter and override the methods beforeArrayValues(…) and writeArrayValueSeparator(…) to archieve the desired behaviour. Afterwards you have to add your new Implementation to your JsonGenerator via setPrettyPrinter(…).

nutlike
  • 4,835
  • 1
  • 25
  • 33
7

Mapper can be configured (jackson-2.6) with:

ObjectMapper mapper = ...
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter();
prettyPrinter.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
mapper.setDefaultPrettyPrinter(prettyPrinter);

//use mapper 
raisercostin
  • 8,777
  • 5
  • 67
  • 76
2

The answer thankfully provided by OP shows a way for obtain a single-array-element-per-line formatted JSON String from writeValueAsString. Based on it here a solution to write the same formatted JSON directly to a file with writeValue with less code:

private static class PrettyPrinter extends DefaultPrettyPrinter {
    public static final PrettyPrinter instance = new PrettyPrinter();

    public PrettyPrinter() {
        _arrayIndenter = Lf2SpacesIndenter.instance;
    }
}

{
    ObjectMapper mapper = new ObjectMapper();
    ObjectWriter writer = mapper.writer(PrettyPrinter.instance);
    writer.writeValue(destFile, objectToSerialize);
}
Community
  • 1
  • 1
Cwt
  • 8,206
  • 3
  • 32
  • 27
-1

try out JSON Generator...

API Reference
good example

eppej
  • 119
  • 17