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.