2026-09-04 · Q&A guide

Fixing Ignored @JsonPropertyOrder in Jackson with Spark

Learn why Jackson's @JsonPropertyOrder can be bypassed when using wrapper objects in Spark and how to enforce the declared field order.

Why @JsonPropertyOrder Seems Ignored

Jackson respects the order you declare **only** for the class that is directly serialized. In your response the root object is a wrapper that contains a field called `infoList`. The wrapper is serialized first, then each `Info` instance is written. If the wrapper uses a `Map` or a generic `ObjectNode`, Jackson falls back to its default ordering (alphabetical or insertion order), which hides the order you set on `Info`.

Check the Container Type

If `infoList` is declared as `Map<String,Object>` or you build the response with `JsonNode`/`ObjectNode`, the order of nested objects is not guaranteed. Use a concrete POJO for the whole response or a `List<Info>` directly.

public class ApiResponse {
    private int status;
    private Result result;
    // getters/setters
}

public class Result {
    private List<Info> infoList;
    // getters/setters
}

Configure the ObjectMapper Correctly

Make sure the mapper is created **once** and that the `MapperFeature.SORT_PROPERTIES_ALPHABETICALLY` feature is disabled (it is off by default, but some frameworks enable it). Also, register the `JacksonAnnotationIntrospector` if you use custom modules.

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, false);
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// reuse this mapper for all responses

Spark Integration Tip

When Spark serializes the return value, it may wrap it in a `JsonTransformer` that creates a `Map<String,Object>` internally. Provide your own transformer that writes the POJO with the pre‑configured mapper, ensuring the order stays intact.

public class JacksonTransformer implements ResponseTransformer {
    private final ObjectMapper mapper;
    public JacksonTransformer(ObjectMapper mapper) { this.mapper = mapper; }
    @Override
    public String render(Object model) throws Exception {
        return mapper.writeValueAsString(model);
    }
}

// usage in Spark route
get("/info", (req, res) -> service.getInfo(), new JacksonTransformer(mapper));

Verify the Result

Run the endpoint and inspect the JSON. The fields inside each `Info` object should now follow the order `id, company, title, infos, startDate, endDate` as declared in `@JsonPropertyOrder`.

Takeaway: Use a concrete POJO for the whole response and a single, properly configured ObjectMapper; then @JsonPropertyOrder works as expected.

People also ask

Does @JsonPropertyOrder work with Lombok @Data?

Yes, Lombok only generates getters/setters. The annotation is processed by Jackson at runtime, independent of Lombok.

What if I need dynamic fields after the ordered ones?

Add a `Map<String,Object>` field annotated with `@JsonAnyGetter` at the end of the class; Jackson will place it after the ordered properties.

Inspired by a public discussion on Stack Overflow. This article is an original explanation for learners.

← All posts