Format JSON in Java: Jackson, Gson, and the 1-space indent default
Java gives you three mainstream choices for formatting JSON: Jackson, Gson, and org.json. Jackson is the de facto standard but its default pretty printer indents with one space, which surprises everyone the first time.
Jackson is the default in modern Java
com.fasterxml.jackson.databind.ObjectMapper is the default JSON layer in Spring Boot, Micronaut, and Quarkus. The pretty path is writerWithDefaultPrettyPrinter():
ObjectMapper mapper = new ObjectMapper();
String pretty = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(obj);
The output is valid, indented JSON. The first time you read it, you notice the indent is one space, not two or four. This is intentional, documented, and the source of an open issue thread that has been alive for a decade. The default printer ships a single space because the library author preferred a compact pretty form.
Most teams want the more conventional 2-space indent. To get it, instantiate DefaultPrettyPrinter and override the indenter:
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
DefaultIndenter indenter = new DefaultIndenter(" ", DefaultIndenter.SYS_LF);
printer.indentObjectsWith(indenter);
printer.indentArraysWith(indenter);
Two spaces, system line endings, applied to both objects and arrays.
Sorting keys for deterministic output
Diffs and snapshot tests need stable key order. Jackson supports two flavors: at ObjectMapper level via SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, and at type level via @JsonPropertyOrder(alphabetic = true). The feature flag affects every map you serialize through that mapper. The annotation only affects the annotated class.
ObjectMapper mapper = new ObjectMapper()
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
Heads up: this only orders Map instances. POJO field order follows the class declaration order or the explicit annotation. If your output has both, you get class fields in declaration order followed by map entries in alphabetical order. Mixed sources in the same JSON object happen rarely in practice; when they do, lock the order with @JsonPropertyOrder on the class.
Gson is lighter and equally common
Google's Gson is the second most-used library, smaller, and the default in many Android projects. The pretty form goes through GsonBuilder:
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.serializeNulls()
.create();
String json = gson.toJson(obj);
setPrettyPrinting() indents with two spaces by default, which is what most people expect. Gson does not have an "order keys alphabetically" toggle equivalent to Jackson. If you need that, sort the input Map before serialization or use TreeMap end to end.
org.json for tiny dependencies
org.json ships with the JDK on Android and is a sub-megabyte dependency on server JDK. It has no annotations, no databinding, just JSONObject and JSONArray. The pretty form is a single overload:
JSONObject obj = new JSONObject(rawString);
String pretty = obj.toString(2); // 2-space indent
Use it when you parse a single payload, transform a few fields, and emit. Do not use it for object mapping: there is no annotation processor, no schema, and the API encourages stringly-typed code.
Working example
javaimport com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.core.util.DefaultIndenter;
public class FormatJson {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper()
.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
// Force 2-space indent on objects and arrays
DefaultIndenter indenter =
new DefaultIndenter(" ", DefaultIndenter.SYS_LF);
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentObjectsWith(indenter);
printer.indentArraysWith(indenter);
var data = java.util.Map.of(
"user", java.util.Map.of("id", 42, "name", "Ada"),
"tags", java.util.List.of("admin", "beta"),
"active", true
);
String pretty = mapper.writer(printer).writeValueAsString(data);
System.out.println(pretty);
}
} Just need the result?
When you need to read a payload from a curl response or a log line and do not want to spin up a Java project just to format it, paste the JSON into the formatter at aldeacode.com. The output uses 2-space indent, validates as you type, and runs entirely in your browser.
Open JSON Formatter and Validator →Frequently asked questions
Why is Jackson's default indent one space?
DefaultPrettyPrinter ships with a single-space indenter because the library author preferred a compact pretty form. There is no flag to change it globally. Instantiate a DefaultPrettyPrinter, set a DefaultIndenter with two spaces, and pass it to writer(printer).
Does Jackson handle Unicode without escaping by default?
Yes. Jackson outputs literal UTF-8 characters by default. If you need ASCII-only output for a constrained transport, enable JsonGenerator.Feature.ESCAPE_NON_ASCII on the writer. The default is the right choice for most modern systems.
Should I use Jackson or Gson for new code?
Jackson if you are on the JVM server side, especially with Spring or Quarkus. Gson on Android, in scripts, and where startup time matters more than feature surface. Both produce valid, pretty JSON.