Order of JSON objects using Jackson's ObjectMapper

JavaJsonJackson

Java Problem Overview


I'm using ObjectMapper to do my java-json mapping.

ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
ow.writeValue(new File( fileName +".json"), jsonObj);

this is my java class:

public class Relation {

private String id;
private String source;
private String target;
private String label;
private List<RelAttribute> attributes;

public String getId() {
	return id;
}

public void setId(String id) {
	this.id = id;
}

public String getSource() {
	return source;
}

public void setSource(String source) {
	this.source = source;
}

public String getTarget() {
	return target;
}

public void setTarget(String target) {
	this.target = target;
}

public String getLabel() {
	return label;
}
public void setLabel(String label) {
	this.label = label;
}

public void setAttributes(List<RelAttribute> attributes) {
	this.attributes = attributes;
}

public List<RelAttribute> getAttributes() {
	return attributes;
}

}

this is what I get:

{
    "id" : "-75da69d3-79c8-4000-a3d8-b10350a57a7e",
    "attributes" : [ {
      "attrName" : "ID",
      "attrValue" : ""
    }, {
      "attrName" : "Description",
      "attrValue" : "Primary Actor"
    }, {
      "attrName" : "Status",
      "attrValue" : ""
    } ],
    "label" : "new Label",
    "target" : "-46b238ac-b8b3-4230-b32c-be9707f8b691",
    "source" : "-daa34638-061a-45e0-9f2e-35afd6c271e0"
  }

So my question now is, how can I get this json output:

{
    "id" : "-75da69d3-79c8-4000-a3d8-b10350a57a7e",
    "label" : "new Label",
    "target" : "-46b238ac-b8b3-4230-b32c-be9707f8b691",
    "source" : "-daa34638-061a-45e0-9f2e-35afd6c271e0",
    "attributes" : [ {
      "attrName" : "ID",
      "attrValue" : ""
    }, {
      "attrName" : "Description",
      "attrValue" : "Primary Actor"
    }, {
      "attrName" : "Status",
      "attrValue" : ""
    } ]

  }

I want it with same order as in my java declaration. Is there a way to specify it ? Maybe with annotations or stuff like that ?

Java Solutions


Solution 1 - Java

@JsonPropertyOrder({ "id", "label", "target", "source", "attributes" })
public class Relation { ... }

Solution 2 - Java

Do you know there is a convenient way to specify alphabetic ordering?

@JsonPropertyOrder(alphabetic = true)
public class Relation { ... }

If you have specific requirements, here how you configure custom ordering:

@JsonPropertyOrder({ "id", "label", "target", "source", "attributes" })
public class Relation { ... }

Solution 3 - Java

The ordering of fields within a generated .class is indeterminate, so you can't count on that.

If you want specific ordering per class then you'll need to use the one of the approaches specified in other answers.

If you want everything to default to alphabetical ordering (e.g. for consistency in how the JSON is structured) then you can configure the ObjectMapper like this:

ObjectMapper mapper = new ObjectMapper();
mapper.setConfig(mapper.getSerializationConfig()
   .with(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));

For more consistent JSON consider also adding:

   .with(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)

One advantage of this approach is that you don't have to modify each class being serialized.

Solution 4 - Java

I discovered a third way today in case alphabetic is not your desired sorting order. It turns out adding a @JsonProperty annotation on a field places it last when writing. I discovered that when I wanted to specify a property name which did not conform to java naming conventions.

By Adding an index attribute you can define the order. Lowest index is placed first.

@JsonProperty(index=20)
String prop1;

@JsonProperty(index=10)
String prop2;

Would render:

{"prop2": "valueProp2", "prop1": "valueProp1"}

Solution 5 - Java

You can use @XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "response", propOrder = { "prop1", "prop2",
		"prop3", "prop4", "prop5", "prop6" }).

@JsonPropertyOrder requires a new jar to be added.

Solution 6 - Java

As per this documentation, you can configure Jackson2ObjectMapperBuilder globally. This class is available in spring-web dependency.

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
      Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
      builder.featuresToEnable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY);
      return builder;
}

Also, you can use @JsonProperty(index) to determine the order in inherited classes as well.

class animal {
    @JsonProperty(index=2)
    int p1;
    @JsonProperty(index=3)
    int p2;
}

class cat extends animal{
    @JsonProperty(index=1)
    int p3;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjustSaidView Question on Stackoverflow
Solution 1 - JavaAndrey AtapinView Answer on Stackoverflow
Solution 2 - JavanaXa stands with UkraineView Answer on Stackoverflow
Solution 3 - JavajohncurrierView Answer on Stackoverflow
Solution 4 - JavaRythmicView Answer on Stackoverflow
Solution 5 - JavaPrasadView Answer on Stackoverflow
Solution 6 - JavaPrajView Answer on Stackoverflow