杰克逊连载。强制将每个字段包装为对象

Dmi*_*ach 5 java json jackson

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

我有两个具有很多字段的 POJO:

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

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

}
Run Code Online (Sandbox Code Playgroud)

@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
Run Code Online (Sandbox Code Playgroud)

Jackson 按预期生成 JSON:

"profile" : {
  "userAttrs" : [ {
    "ordercode" : 123,
    "transactionid" : 12345,
    "reference" : 123456789,
    "orderpaymenttypecode" : 1231341,
    ... more properties ...
  } ]
}
Run Code Online (Sandbox Code Playgroud)

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

"profile" : {
  "userAttrs" : [ 
    {"ordercode" : 123},
    {"transactionid" : 12345},
    {"reference" : 123456789},
    {"orderpaymenttypecode" : 1231341},
    ... more properties ...
  ]
}
Run Code Online (Sandbox Code Playgroud)

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

也许还有其他方法可以做到?

Man*_*dis 1

我猜想您尝试使用的 Jackson databind 模块旨在将 JSON 文档和 Java 类绑定为具有相同的结构。出于我认为很重要的原因,您需要一个具有不同结构的 JSON 文档、多个单字段对象,而不是像 Java 类中那样的单个多字段对象。我认为在这种情况下你不应该使用 databind 。即使自定义序列化器解决了问题,这也不是它的预期用途。

您可以通过获取树、将其重塑为所需的结构并对修改后的树进行序列化来获得所需的 JSON。假设您已经ObjectMapper mapper并且Profile 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
Run Code Online (Sandbox Code Playgroud)

当您使用以下内容进行序列化时:

mapper.writeValueAsString(profileRoot)
Run Code Online (Sandbox Code Playgroud)

你会在你的问题中得到 JSON