Search code examples
javajsonjacksonjackson2

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.


Solution

  • 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