Как десериализовать массив объектов JSON в Java - PullRequest
1 голос
/ 26 сентября 2019

Так что я привык получать объекты JSON из заданного API / конечной точки, например:

{
    "count": 5,
    "results": [
        {
            "example": "test",
            "is_valid": true
        },
        {
            "example": "test2",
            "is_valid": true
        }
    ]
}

И в пользовательском десериализаторе, который расширяет com.fasterxml.jackson.databind.deser.std. StdDeserializer , я знаю, что могу использовать объект JsonParser таким образом, чтобы заставить базовый узел работать, т.е.:

@Override
public ResultExample deserialize(JsonParser jp, DeserializationContext ctxt) {
    JsonNode node = jp.getCodec().readTree(jp);
    JsonNode count = node.get("count");
    // code to put parsed objects into a ResultExample object...
}

Однако я только что столкнулся с API, который просто возвращает массивобъектов JSON, например:

[
    {
        "example": "test",
        "is_valid": true
    },
    {
        "example": "test2",
        "is_valid": true
    },
]

Итак, я не верю, что могу просто проанализировать это так же, как и раньше.Какой будет правильный способ разобрать это с помощью Джексона?

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Это может помочь вам:

import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Test {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        String json = "[\r\n" + "    {\r\n" + "        \"example\": \"test\",\r\n" + "        \"is_valid\": true\r\n"
                + "    },\r\n" + "    {\r\n" + "        \"example\": \"test2\",\r\n" + "        \"is_valid\": true\r\n"
                + "    }\r\n" + "]";
        Example[] ex = mapper.readValue(json, Example[].class);

    }

}

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({ "example", "is_valid" })
class Example {

    @JsonProperty("example")
    private String example;
    @JsonProperty("is_valid")
    private Boolean isValid;

    public String getExample() {
        return example;
    }

    @JsonProperty("example")
    public void setExample(String example) {
        this.example = example;
    }

    @JsonProperty("is_valid")
    public Boolean getIsValid() {
        return isValid;
    }

    @JsonProperty("is_valid")
    public void setIsValid(Boolean isValid) {
        this.isValid = isValid;
    }
}
0 голосов
/ 28 сентября 2019

Когда ответом является JSON Object, вы можете использовать десериализатор бина по умолчанию.Если это JSON Array, вы можете прочитать его как массив и создать объект ответа вручную.Ниже вы можете найти пример пользовательского десериализатора и BeanDeserializerModifier, который используется для регистрации пользовательского десериализатора.BeanDeserializerModifier позволяет использовать десериализатор по умолчанию, когда подходит JSON полезная нагрузка POJO модель:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionType;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        SimpleModule module = new SimpleModule();
        module.setDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                if (beanDesc.getBeanClass() == Response.class) {
                    return new ResponseJsonDeserializer((BeanDeserializerBase) deserializer);
                }
                return super.modifyDeserializer(config, beanDesc, deserializer);
            }
        });

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(module);


        System.out.println(mapper.readValue(jsonFile, Response.class));
    }
}

class ResponseJsonDeserializer extends BeanDeserializer {

    private final BeanDeserializerBase baseDeserializer;

    protected ResponseJsonDeserializer(BeanDeserializerBase src) {
        super(src);
        this.baseDeserializer = src;
    }

    @Override
    public Response deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        if (p.currentToken() == JsonToken.START_OBJECT) {
            return (Response) baseDeserializer.deserialize(p, ctxt);
        }
        if (p.currentToken() == JsonToken.START_ARRAY) {
            CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, Item.class);
            JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(collectionType);
            List<Item> results = (List<Item>) deserializer.deserialize(p, ctxt);

            Response response = new Response();
            response.setCount(results.size());
            response.setResults(results);

            return response;
        }

        throw MismatchedInputException.from(p, Response.class, "Only object or array!");
    }
}

class Response {

    private int count;
    private List<Item> results;

    // getters, setters, toString
}

class Item {

    private String example;

    @JsonProperty("is_valid")
    private boolean isValid;

    // getters, setters, toString
}

Выше код для JSON Object распечатки полезной нагрузки:

Response{count=5, results=[Item{example='test', isValid=true}, Item{example='test2', isValid=true}]}

И для JSON Array полезные данные:

Response{count=2, results=[Item{example='test', isValid=true}, Item{example='test2', isValid=true}]}
0 голосов
/ 26 сентября 2019

Полагаю, я должен был просто написать модульный тест, прежде чем задавать вопрос, но, очевидно, вы можете сделать это точно так же.Единственное отличие состоит в том, что базовый узел - это JsonArray, который вы должны перебирать.Спасибо всем, кто заглянул в это.

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