杰克逊序列化。强制将每个字段包装为对象

时间:2018-02-09 13:45:16

标签: java json jackson

我知道类似的问题已经asked了。但那个解决方案不适合我。

我有两个POJO,有很多字段:

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Profile {

    @JsonProperty("userAttrs")
    private List<UserAttr> userAttrs;

}

@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserAttr {

  @JsonProperty("ordercode")
  private String ordercode;

  @JsonProperty("transactionid")
  private String transactionid;

  @JsonProperty("receiptno")
  private String receiptno;

  // A lot more fields

杰克逊按预期生产JSON:

"profile" : {
  "userAttrs" : [ {
    "ordercode" : 123,
    "transactionid" : 12345,
    "reference" : 123456789,
    "orderpaymenttypecode" : 1231341,
    ... more properties ...
  } ]
}

但是我需要将每个属性包装为JSON对象。像这样:

"profile" : {
  "userAttrs" : [ 
    {"ordercode" : 123},
    {"transactionid" : 12345},
    {"reference" : 123456789},
    {"orderpaymenttypecode" : 1231341},
    ... more properties ...
  ]
}

我不想为每个字段创建单独的POJO。另一种方法是为每个字段创建Map,但这是一个糟糕的决定。

也许有其他方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

我认为你试图使用的Jackson数据库模块用于绑定具有相同结构的JSON文档和Java类。由于我信任的重要原因,您需要一个具有不同结构的JSON文档,多个单字段对象而不是Java类中的单个多字段对象。我认为你不应该在这种情况下使用数据绑定。即使自定义序列化程序解决了这个问题,这也不是它的预期用途。

您可以通过获取树来获取所需的JSON,将其重新整理为所需的结构并对修改后的树进行处理。假设您有ObjectMapper mapperProfile profile,则可以执行以下操作:

JsonNode profileRoot = mapper.valueToTree(profile);
ArrayNode userAttrs = (ArrayNode) profileRoot.get("userAttrs");
userAttrs.get(0).fields().forEachRemaining(userAttrs::addPOJO);
userAttrs.remove(0); // remove original multi-field object

然后用以下内容序列化:

mapper.writeValueAsString(profileRoot)

您将在问题中获得JSON