Добавление динамического свойства json как java pojo для Джексона - PullRequest
2 голосов
/ 21 мая 2019

Мне нужно создать полезную нагрузку Json, например, из Java pojo:

{ "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; 
    }
  }
}

Мне нравится иметь свойство add в классе Label как динамическое, чтобы оно также могло принимать значения, такие как «remove», «set». Есть ли способ сделать это, кроме создания другого POJO для каждого из них?

Ответы [ 2 ]

1 голос
/ 22 мая 2019

Вы можете использовать JsonAnyGetter аннотацию, которая позволяет создавать динамические пары key-value.Ниже приведен пример того, как мы можем сгенерировать 3 разных ключа для одного и того же Label класса:

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"
  } ]
}

См. Также:

1 голос
/ 22 мая 2019

Ваша спецификация не ясна, у вас будет много одинаковых действий (добавление, удаление и т. Д.) Или не более одного?

Первый вариант
В случаеу вас есть не более одного экземпляра того же действия, вы можете заменить массив обычным объектом:

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

, а затем изменить свои метки на Map<String, String> вместо List<Label>

Второй вариант
Если у вас много экземпляров одного и того же действия, вы можете изменить дизайн метки так, чтобы он содержал два поля: value и action

{ "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.возможно, это можно как-то взломать, используя полиморфизм Джексона.Но вы всегда можете просто использовать объекты json и оставить метки как List<JsonObject>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...