【问题标题】:Order of JSON objects using Jackson's ObjectMapper使用 Jackson 的 ObjectMapper 的 JSON 对象的顺序
【发布时间】:2013-10-16 20:37:21
【问题描述】:

我正在使用 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 声明中的顺序相同。有没有办法指定它?也许带有注释或类似的东西?

【问题讨论】:

  • 属性顺序很重要表明代码/设计气味。任何消费 JSON 的东西都不应该关心顺序(列出是,属性不是)。
  • 为了可读性我只需要它:-)
  • @ach 这不是真的。有序映射是一种非常常见且非常有用的数据类型。想要秩序根本不是气味。
  • 不,它不是代码/设计的味道。考虑一个您签署/验证 json 数据的 scrnario。
  • @Honza Zidek 我的评论是 7 年前的,但我只能想象它是针对互操作性的(第二句支持作为评论的目的)。我仍然坚持这一点——JSON 规范没有提供属性排序要求是有原因的,JSON 模式 AFAIR 也没有。为了可读性而排序的属性是合理的。

标签: java json jackson


【解决方案1】:
@JsonPropertyOrder({ "id", "label", "target", "source", "attributes" })
public class Relation { ... }

【讨论】:

    【解决方案2】:

    您知道有一种方便的方法来指定字母顺序吗?

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

    如果您有特定要求,请在此处配置自定义排序:

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

    【讨论】:

      【解决方案3】:

      生成的 .class 中的字段顺序是不确定的,因此您不能指望它。

      如果您希望按类进行特定排序,则需要使用其他答案中指定的方法之一。

      如果您希望所有内容都默认为字母顺序(例如,为了保持 JSON 结构的一致性),那么您可以像这样配置 ObjectMapper:

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

      对于更一致的 JSON,还可以考虑添加:

         .with(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
      

      这种方法的一个优点是您不必修改每个被序列化的类。

      【讨论】:

        【解决方案4】:

        我今天发现了第三种方法,以防字母顺序不是您想要的排序顺序。事实证明,在字段上添加 @JsonProperty 注释会在写入时将其放在最后。我发现当我想指定一个不符合 java 命名约定的属性名称时。

        通过添加索引属性,您可以定义顺序。最低的索引放在第一位。

        @JsonProperty(index=20)
        String prop1;
        
        @JsonProperty(index=10)
        String prop2;
        

        将呈现:

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

        【讨论】:

        • 这是最好的解决方案
        【解决方案5】:

        您可以使用@XmlAccessorType(XmlAccessType.FIELD)

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

        @JsonPropertyOrder 需要添加一个新的 jar。

        【讨论】:

        • @JsonPropertyOrder 不需要新 jar,因为如果您使用 jackson,它已经包含在内。
        • 这取决于你使用的框架。如果你不使用jackson,那么最好使用上面的实现,它适用于json和xml,如果你想返回数据不需要额外的配置xml格式
        • 是的,但问题是通过使用 jackson 提出的。如果您想在不使用 jackson 的情况下提供解决方案,您的答案必须更加具体。
        【解决方案6】:

        根据this documentation,您可以全局配置 Jackson2ObjectMapperBuilder。这个类在 spring-web 依赖中可用。

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

        此外,您也可以使用@JsonProperty(index) 来确定继承类中的顺序。

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

        【讨论】:

          猜你喜欢
          • 2015-02-19
          • 1970-01-01
          • 2019-08-21
          • 1970-01-01
          • 2021-12-13
          • 2020-08-23
          • 2022-01-10
          • 2021-10-05
          相关资源
          最近更新 更多