ksl ksl - 2 months ago 13
JSON Question

Jackson - Using custom PrettyPrinter with custom JsonSerializer

I am using Jackson v2.8.2 to serialise JSON to a file.

I have created a custom serializer and implemented the

serialize
method to customise the JSON output as required.

I am invoking the serializer as follows:

// 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)
{
...
}


The JSON file is created and the content looks good.

The file is formatted according to the
DefaultPrettyPrinter
but I want to use my own custom
PrettyPrinter
, which I have already implemented.

How do I do that?

I've tried the following:

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


but that isn't invoking my custom printer.

Answer

The reason for this is that the invocation of writer returns a new instance of the ObjectWriter. In fact, ObjectMapper has a lot of factory methods that construct new objects for you to work with.

The sourcecode from 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);
    }

So for you that means, that you should change your code to:

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

Note the assignment to myWriter so that you are using the correct writer when calling writeValue

Here is an example using the ObjectMapper and the default pretty printer:

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));
    }
}

This prints:

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

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

Where the first line uses the mapper, while the second print uses the writer.

Cheers,

Artur