I need to create a Json payload like this from Java pojo :
{ \"update\" : {
\"labels\" : [{\"add\" : \"A label\"} ]
}
}
so I crea
You can use JsonAnyGetter annotation which allows to create dynamic key-value
pairs. Below example shows how we can generate 3 different keys for the same Label
class:
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class JsonApp {
public static void main(String[] args) throws Exception {
AddLabel label = new AddLabel("A label");
label.getLabels().add(AddLabel.Label.remove("Remove"));
label.getLabels().add(AddLabel.Label.set("Set"));
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(label));
}
}
@JsonRootName(value = "update")
class AddLabel {
@JsonProperty("labels")
private List<Label> labels;
public AddLabel(String labelName) {
this.labels = new ArrayList<>();
this.labels.add(Label.add(labelName));
}
public List<Label> getLabels() {
return labels;
}
public static class Label {
private final String key;
private final String value;
private Label(String key, String value) {
this.key = key;
this.value = value;
}
public static Label add(String value) {
return new Label("add", value);
}
public static Label remove(String value) {
return new Label("remove", value);
}
public static Label set(String value) {
return new Label("set", value);
}
@JsonAnyGetter
public Map<String, String> getDynamic() {
return Collections.singletonMap(key, value);
}
}
}
Above code prints:
{
"labels" : [ {
"add" : "A label"
}, {
"remove" : "Remove"
}, {
"set" : "Set"
} ]
}
See also:
Your specification isn't clear, you would have many of the same action (add, remove, etc) or just one at most?
First Option
In case you have at most single instance of the same action, you can replace the array with regular object:
{ "update" : {
"labels" : {
"add" : "A label",
"remove" : "B label"
}
}
}
and then change your labels to a Map<String, String>
instead of List<Label>
Second Option
In case you have many instances of the same action, you can change the design of label to contain two fields, value
and action
{ "update" : {
"labels" : [{"action": "add", "value" : "A label"} ]
}
}
And update Label
accordingly:
public static class Label{
public String action;
public String value
public Label(String action, String value){
this.action = action;
this.value = value;
}
}
You can also change action
to enum
which define all your possible actions
Third Option
If you really need to stick to your json design, you don't have a lot of options to define static typing class for a dynamic json. maybe it's possible to hack this somehow using jackons's polymorphism. But you can always just use the json objects and leave the labels as List<JsonObject>