【问题标题】:Adding a dynamic json property as java pojo for jackson为jackson添加一个动态json属性作为java pojo
【发布时间】:2019-10-08 06:52:55
【问题描述】:

我需要从 Java pojo 创建一个像这样的 Json 有效负载:

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

所以我创建了一个这样的 Java pojo:

@JsonRootName(value = "update")
public class AddLabel{
  @JsonProperty("labels")
  public List<Label> labels; 
  public AddLabel(String labelName){
     this.labels = new ArrayList<>(); 
     this.labels.add(new Label(labelName); 
  }
  public static class Label{
    public String add; 
    public Label(String labelName){
       this.add = labelName; 
    }
  }
}

我喜欢将 Label 类中的“add”属性设置为动态的,这样它也可以采用“remove”、“set”等值。除了为每个人创建另一个 POJO 之外,还有其他方法吗?

【问题讨论】:

    标签: java jackson


    【解决方案1】:

    您可以使用JsonAnyGetter 注释,它允许创建动态key-value 对。下面的示例展示了我们如何为同一个 Label 类生成 3 个不同的键:

    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);
            }
        }
    }
    

    上面的代码打印:

    {
      "labels" : [ {
        "add" : "A label"
      }, {
        "remove" : "Remove"
      }, {
        "set" : "Set"
      } ]
    }
    

    另见:

    【讨论】:

      【解决方案2】:

      您的规范不明确,您会有许多相同的操作(添加、删除等)还是最多只有一个?

      第一个选项
      如果您最多有一个相同动作的实例,您可以将数组替换为常规对象:

      { "update" : {
          "labels" : {
             "add" : "A label",
             "remove" : "B label"
            }
          }
       }
      

      然后将您的标签更改为 Map&lt;String, String&gt; 而不是 List&lt;Label&gt;

      第二个选项
      如果您有许多相同操作的实例,您可以更改标签的设计以包含两个字段,valueaction

      { "update" : {
          "labels" : [{"action": "add", "value" : "A label"} ]
          }
       }
      

      并相应地更新Label

        public static class Label{
          public String action;
          public String value 
          public Label(String action, String value){
             this.action = action;
             this.value = value; 
          }
        }
      

      您还可以将action 更改为enum,它定义了您所有可能的操作

      第三个选项
      如果你真的需要坚持你的 json 设计,你没有很多选择来为动态 json 定义静态类型类。也许有可能使用jackons的多态性以某种方式破解它。但是您始终可以只使用 json 对象并将标签保留为 List&lt;JsonObject&gt;

      【讨论】:

        猜你喜欢
        • 2017-12-24
        • 2020-02-20
        • 1970-01-01
        • 2020-03-18
        • 1970-01-01
        • 1970-01-01
        • 2013-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多