【问题标题】:Jackson error: Cannot deserialize instance of `java.lang.String` out of START_ARRAY tokenJackson 错误:无法从 START_ARRAY 令牌中反序列化 `java.lang.String` 的实例
【发布时间】:2020-06-16 20:16:43
【问题描述】:

嘿,我的 Json 也有问题

[
{
    "aimid": "12345"
},
{
    "aimid": "333674"
},
{
    "aimid": [
        "4568999",
        "6789345"
    ]
}]

这是我的 Pojo 课程:-

@JsonProperty("aimid")
private String aimid;


public String getAimid() {
    return aimid;
}

public void setAimid(String aimid) {
    this.aimid = aimid;
}

我想将目标存储在 pojo 中。当我在我的应用程序中像上面那样写时,我遇到了错误。

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token.

据我了解,由于 Array 元素,我遇到了错误,因此任何人都可以建议我如何捕获这两个东西,如果它是作为字符串出现的,还是作为数组字符串出现的

【问题讨论】:

  • 如果您收到一个包含两个不同值的数组,您希望得到的 aimid 究竟是什么?
  • @ErichKitzmueller 看到我正在消耗休息 Api,因为所有数据都即将到来。因此,为了捕获这些数据,我现在在我的 api 中创建了 pojo 类,我将使用这个 pojo。所以我需要捕获什么数据,然后我需要使用它。所以无论有什么目标,我都需要捕捉..
  • 你的 api 数据结构不好,不能顺利完成!您需要更改您的 api 响应,或者如果无法调整 api 响应,则必须执行一些手动任务
  • 那么你能告诉我我可以在哪里以及如何手动执行任务,因为无法修改响应..@user404

标签: java spring-boot pojo jackson-databind jackson2


【解决方案1】:

挑战在于,在某些情况下“aimid”是一个字符串值,但在另一种情况下它是一个数组。

如果您可以控制 JSON 的结构,请更新结构,以便根数组的每个元素都具有以下结构之一:

字符串 { “艾米德”:“333674” } 或数组 { “艾米德”:[ "4568999", “6789345” ] }

如果您无法控制数据结构,则需要自己解析数据并将其处理到 POJO 中。

请查看这 3 个代码示例,它们应该说明您可以如何使用这种方法。 :

public class MyPojo {

    private List<String> aimid;

    @JsonProperty("aimid")
    public List<String> getAimid() {
    return aimid;
    }

    @JsonProperty("aimid_array")
    public void setAimid(final List<String> aimid) {
    this.aimid = aimid;
    }

    @JsonProperty("aimid")
    public void setAimid(final String aimid) {
    this.aimid = Arrays.asList(aimid);
    }
}


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.*;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Test;

    public class UnitTest {

    private static final Logger LOGGER = Logger.getLogger(UnitTest.class.getName());

    public UnitTest() {
    }

    @Test
    public void testOneAimId() throws IOException {
    final String json = "[\n"
        + "{\n"
        + "    \"aimid\": \"12345\"\n"
        + "},\n"
        + "{\n"
        + "    \"aimid\": \"333674\"\n"
        + "}]";
    final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
    });
    log(Level.SEVERE, LOGGER, "testOneAimId", result);
    }

    @Test
    public void testListAimIds() throws IOException {
    final String json = "[\n"
        + "{\n"
        + "    \"aimid_array\": [\n" // HERE WE HAVE CHANGED THE JSON PROP NAME
        + "        \"4568999\",\n"
        + "        \"6789345\"\n"
        + "    ]\n"
        + "}]";
    final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
    });
    log(Level.SEVERE, LOGGER, "testListAimIds", result);
    }

    @Test
    public void testMixed() throws IOException {
    final String json = "[\n"
        + "{\n"
        + "    \"aimid\": \"12345\"\n"
        + "},\n"
        + "{\n"
        + "    \"aimid\": \"333674\"\n"
        + "},\n"
        + "{\n"
        + "    \"aimid_array\": [\n" // HERE WE HAVE CHANGED THE JSON PROP NAME
        + "        \"4568999\",\n"
        + "        \"6789345\"\n"
        + "    ]\n"
        + "}]";
    final List<MyPojo> result = new ObjectMapper().readValue(json, new TypeReference<List<MyPojo>>() {
    });
    log(Level.SEVERE, LOGGER, "testMixed", result);
    }

    @Test
    public void testMixed2() throws IOException {
    final String json = "[\n"
        + "{\n"
        + "    \"aimid\": \"12345\"\n"
        + "},\n"
        + "{\n"
        + "    \"aimid\": \"333674\"\n"
        + "},\n"
        + "{\n"
        + "    \"aimid\": [\n"
        + "        \"4568999\",\n"
        + "        \"6789345\"\n"
        + "    ]\n"
        + "}]";

    final JsonNode result = new ObjectMapper().readValue(json, JsonNode.class);
    final ArrayList<String> arrayList = new ArrayList<>();

    result.forEach((final JsonNode jsonNode) -> {

        if (jsonNode.getNodeType() != JsonNodeType.OBJECT)
        throw new IllegalArgumentException(jsonNode.toString());

        final ObjectNode obj = (ObjectNode) jsonNode;
        obj.forEach(o -> {
        switch (o.getNodeType()) {
            case ARRAY:
            final ArrayNode array = (ArrayNode) o;
            array.forEach(t -> arrayList.add(t.asText()));
            break;
            case STRING:
            arrayList.add(o.asText());
            break;
            default:
            throw new IllegalArgumentException(o.toString());
        }
        });
    });

    final MyPojo myPojo = new MyPojo();
    myPojo.setAimid(arrayList);
    log(Level.SEVERE, LOGGER, "myPojo", myPojo);
    }

    private void log(final Level level, final Logger logger, final String title, final Object obj) {
    try {
        if (title != null)
        logger.log(level, title);
        final ObjectWriter writer = new ObjectMapper().writerWithDefaultPrettyPrinter();
        logger.log(level, obj == null ? "null" : writer.writeValueAsString(obj));
    } catch (final JsonProcessingException ex) {
        logger.log(Level.SEVERE, ex.getMessage(), ex);
    }
    }
}

【讨论】:

  • 我认为它会起作用,让我实现它,非常感谢您的回复..
  • 谢谢 deepak 应该有一个选项下方的投票按钮 (meta.stackexchange.com/questions/5234/…)
  • 嘿@Jev Prentice .. 正如你在解决方案@JsonProperty("aimid_array") 中提到的,但我在这两种情况下都有相同的名称,所以如果我有不同类型的相同名称,你如何写得不同。 .
  • 嗨@DeepakKumar 我认为您可能需要更手动地将json(从字符串)解析为POJO,看看testMixed2()中的示例代码
  • 嘿@Jev Prentice .. 几天前我能够解决这个问题,而不是定义像 Array 和 JSONArray 这样的类型,我们可以将 read 分配为 Object 然后我们可以检查它的实例并转换它根据我们的要求以任何形式并将其设置在 getMethod....
猜你喜欢
  • 1970-01-01
  • 2015-03-10
  • 1970-01-01
  • 2014-06-23
  • 2015-01-04
  • 2019-12-13
  • 1970-01-01
  • 2018-03-05
  • 2018-05-22
相关资源
最近更新 更多