使用 Jackson 的 ObjectMapper 排列 JSON 对象的顺序

我使用 ObjectMapper来做 java-json 映射。

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

这是我的 Java 课:

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;
}


}

这就是我得到的:

{
"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"
}

现在我的问题是,如何得到这个 json 输出:

{
"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" : ""
} ]


}

我希望它的顺序和我的 Java 声明中的一样。有什么方法能说明吗?也许有注释之类的东西?

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

You can use @XmlAccessorType(XmlAccessType.FIELD)

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

@JsonPropertyOrder requires a new jar to be added.

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 { ... }

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.

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"}

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;
}