Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson serialization. Force to wrap each field as object

Tags:

java

json

jackson

I know that similar question was already asked. But that solution don't suit me.

I have two POJOs with quite a lot of fields:

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

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

}

And

@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

Jackson produces JSON as expected:

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

However I need to wrap each property as JSON Object. Something like this:

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

I don't want to create separate POJO for every field. The other way is to create Map for every field, but this is a bad decision.

Maybe there are some other ways to do it?

like image 650
Dmitry Kach Avatar asked Nov 08 '22 10:11

Dmitry Kach


1 Answers

The Jackson databind module, that I presume you tried to use, is meant to bind JSON documents and Java classes with the same structure. For reasons that I trust are important, you want a JSON document with a different structure, multiple single-field objects instead of a single multi-field object as you have in the Java class. I'd argue you shouldn't use databind in this case. That's not its intended use even if a custom serializer solves the problem.

You can get the JSON you want by obtaining a tree, reshaping it to the desired structure and serliazing the modified tree. Assuming you have ObjectMapper mapper and Profile profile you can do:

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

When you then serialize with something like:

mapper.writeValueAsString(profileRoot)

you'll get the JSON in your question

like image 190
Manos Nikolaidis Avatar answered Nov 14 '22 20:11

Manos Nikolaidis