Adding a dynamic json property as java pojo for jackson

后端 未结 2 1349
滥情空心
滥情空心 2020-12-07 04:13

I need to create a Json payload like this from Java pojo :

{ \"update\" : {
    \"labels\" : [{\"add\" : \"A label\"} ]
    }
 }

so I crea

相关标签:
2条回答
  • 2020-12-07 04:55

    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:

    • Jackson @JsonAnyGetter and @JsonAnySetter Example
    • Jackson Annotation Examples
    • How to use dynamic property names for a Json object
    0 讨论(0)
  • 2020-12-07 04:55

    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>

    0 讨论(0)
提交回复
热议问题