30

How do I make Jackson's build() method pretty-print its JSON output? is an example that pretty-prints the JSON string.

I need to take the pretty-printed version of JSON string and then convert it to the compact/minified form. How can it be done?

I need to convert this:

{
  "one" : "AAA",
  "two" : [ "B B", "CCC" ],
  "three" : {
    "four" : "D D",
    "five" : [ "EEE", "FFF" ]
  }
}

to this:

{"one":"AAA","two":["B B","CCC"],"three":{"four":"D D","five":["EEE","FFF"]}}

I tried to remove '\n', '\t', and ' ' characters; but there may be some of these characters in values so I can't do that.

What else can be done?

Andrew T.
  • 4,701
  • 8
  • 43
  • 62
mtyurt
  • 3,369
  • 6
  • 38
  • 57
  • 2
    How about reading the pretty-printed data back into Jackson and then output it again without pretty-print enabled? See [converting a String to JSON](http://stackoverflow.com/questions/6591388/converting-a-string-to-json-in-java) – Brad Aug 29 '12 at 08:35

4 Answers4

32

Jackson allows you to read from a JSON string, so read the pretty-printed string back into Jackson and then output it again with pretty-print disabled.

See converting a String to JSON

Simple Example

    String prettyJsonString = "{ \"Hello\" : \"world\"}";
    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode jsonNode = objectMapper.readValue(prettyJsonString, JsonNode.class);
    System.out.println(jsonNode.toString());

Requires

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.5.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.5.3</version>
</dependency>
Community
  • 1
  • 1
Brad
  • 15,186
  • 11
  • 60
  • 74
8

The safe way is to read the data using the JsonNode API and just write it out again without enabling the pretty printer.

ObjectMapper m = new ObjectMapper();
JsonNode rootNode = m.readTree(payload);
String compressed = rootNode.toString();

If the object is huge, the Streaming API can help.

Using a regexp does also work if you use this pattern: \s*\n\s*

This doesn't create the most compact form (i.e. you will still have some spaces between elements) but it's a cheap solution if you already have the JSON as a String. The reason why this pattern is safe is that new lines are invalid in String values (they must be escaped using \n) so you can safely remove whitespace around them.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
8

With the streaming API, you can use JsonGenerator.copyCurrentEvent() to easily re-output the token stream with whatever pretty-printing applied you want, including the default of no whitespace; this avoids buffering the entire document in memory and building a tree for the document.

// source and out can be streams, readers/writers, etc.
String source = "   { \"hello\" : \" world \"  }  ";
StringWriter out = new StringWriter();

JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(source);
try (JsonGenerator gen = factory.createGenerator(out)) {
    while (parser.nextToken() != null) {
        gen.copyCurrentEvent(parser);
    }
}

System.out.println(out.getBuffer().toString()); // {"hello":" world "}

You can use the same approach to pretty-print a JSON document in a streaming fashion:

// reindent
gen.setPrettyPrinter(new DefaultPrettyPrinter());
Miles
  • 31,360
  • 7
  • 64
  • 74
7

Jackosn-core is one way of pretty printing json. You can read the answer here https://stackoverflow.com/a/12174201/432903

You can also use org.json library, which is a very simple but standard json lib for java. Open source code here -> stleary/JSON-java.

maven dependency

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>

usage

        String payload = "{\n" +
            "  \"fact1\": \"Java is verbose.\", \n" +
            "  \"fact2\" : \"C has pointers\"\n" +
            "}";
        System.out.println(new JSONObject(payload));

You'll get compact json {"fact2":"C has pointers","fact1":"Java is verbose."} in one line.

prayagupa
  • 30,204
  • 14
  • 155
  • 192