【问题标题】:How to Deserialize Array of JSON Objects in Java如何在 Java 中反序列化 JSON 对象数组
【发布时间】:2019-09-26 19:11:27
【问题描述】:

所以我习惯于从给定的 API/端点获取 JSON 对象,例如:

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

所以,我不相信我可以像以前一样解析这个。使用 Jackson 解析这个的正确方法是什么?

【问题讨论】:

  • 你能再贴一些代码吗? jp 是什么?
  • jp 是上面提到的 JsonParser。我将继续为上下文添加更多代码。

标签: java arrays json jackson deserialization


【解决方案1】:

这可能会对您有所帮助:

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

【讨论】:

  • 您好,我也在以类似的方式进行操作,例如我有 json 对象数组,但收到此错误 com.fasterxml.jackson.databind.JsonMappingException: (was java.io.IOException) (通过引用链: java.lang.Object[][0])↵
【解决方案2】:

当响应为JSON Object 时,您可以使用默认的 bean 反序列化器。如果它是JSON Array,您可以将其读取为数组并手动创建响应对象。您可以在下面找到示例自定义解串器和用于注册自定义解串器的BeanDeserializerModifier。当JSON 有效负载适合POJO 模型时,BeanDeserializerModifier 允许使用默认反序列化器:

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

【讨论】:

    【解决方案3】:

    我想我应该在提问之前写好单元测试,但显然你可以用同样的方式来做。唯一的区别是基节点是一个 JsonArray ,您必须对其进行迭代。感谢所有对此进行调查的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      • 2016-09-23
      • 2015-06-11
      • 2019-01-14
      相关资源
      最近更新 更多