Десериализация вложенного JSONObject в JSONObject

#java #json #serialization #jackson #deserialization

#java #json #сериализация #джексон #десериализация

Вопрос:

Итак, я работаю над десериализацией вложенного JSONObject, но не хочу создавать класс для каждого вложенного объекта. Я пытался использовать один из вложенных JSONObjects и поместить его в JSONObject.

 public class ContainerStatus {

@JsonProperty("name")
private String name;
@JsonProperty("state")
private JSONObject state;
@JsonProperty("lastState")
private JSONObject  lastState;
@JsonProperty("ready")
private Boolean ready;
@JsonProperty("restartCount")
private Integer restartCount;
@JsonProperty("image")
private String image;
@JsonProperty("imageID")
private String imageID;
@JsonProperty("containerID")
private String containerID;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
  

Используя это для десериализации:

  { "containerStatuses": 
        {
            "name": "connect",
            "state": {
                        "terminated": {
                            "exitCode": 1,
                            "reason": "Error",
                            "startedAt": "2019-03-20T15:40:08Z",
                            "finishedAt": "2019-03-20T15:40:50Z",
                            "containerID": "docker://"
                        }
                    },
            "lastState": {},
            "ready": true,
            "restartCount": 0,
            "image": "image",
            "imageID": "docker-pullable://",
            "containerID": "docker://"
        }}
  

Я получаю нераспознанное поле «terminated» из-за состояния JSONObject.

Я хочу:

JsonObject state = {
"terminated": {
"exitCode": 1,
"reason": "Error",
"startedAt": "2019-03-20T15:40:08Z",
"finishedAt": "2019-03-20T15:40:50Z",
"containerID": "docker://"
}
}

Я могу преобразовать его в универсальный объект, но формат больше не JSON:

 @JsonProperty("state")
private Object state;

Gives me this format:
{running={startedAt=2019-03-20T14:53:53Z}}
  

Ответ №1:

Вам нужно немного улучшить свой пример:

  • DeserializationFeature.UNWRAP_ROOT_VALUE , включите эту функцию для разворачивания JSON объекта.
  • Добавьте JsonRootName аннотацию к вашему POJO классу, потому что имя класса не совпадает со свойством containerStatuses .
  • Используйте JsonNode то, что поступает из Jackson библиотеки, вместо JSONObject того, что, вероятно, поступает из org.json .

Улучшенный пример может выглядеть следующим образом:

 import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        String json = "{...}";
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);

        ContainerStatus cs = mapper.readValue(json, ContainerStatus.class);
        System.out.println(cs.getState());
    }
}

@JsonRootName("containerStatuses")
class ContainerStatus {

    @JsonProperty("name")
    private String name;
    @JsonProperty("state")
    private JsonNode state;
    @JsonProperty("lastState")
    private JsonNode lastState;
    @JsonProperty("ready")
    private Boolean ready;
    @JsonProperty("restartCount")
    private Integer restartCount;
    @JsonProperty("image")
    private String image;
    @JsonProperty("imageID")
    private String imageID;
    @JsonProperty("containerID")
    private String containerID;

    // getters, setters, toString
}
  

Приведенный выше код выводит:

 {"terminated":{"exitCode":1,"reason":"Error","startedAt":"2019-03-20T15:40:08Z","finishedAt":"2019-03-20T15:40:50Z","containerID":"docker://"}}
  

Комментарии:

1. Изменение его на JsonNode решило проблему, и теперь я получаю его как JSON. Спасибо!