当前位置: 首页 > 知识库问答 >
问题:

多次调用ObjectMapper readValue,直到抛出StackOverflowException

羊舌炯
2023-03-14

我试图为我的值类构建一个自定义反序列化器类。但是ObjectMapper. readValue会被多次调用,直到抛出StackOverflow异常。以下只是一个例子:

@JsonDeserialize(using = UserDeserializer.class)
@Getter
public class User {
    private String name;
}

public class UserDeserializer extends StdDeserializer<User> {
    public UserDeserializer() {
        super(User.class);
    }

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return ctxt.readValue(p, User.class);
    }
}

public class UserDeserializerTest {
    @Test
    public void whenUserIsDeserializedFromJsonThenNameShouldEqualBob() {
        String = "{ \"name\" : \"bob\" }";
        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(json, User.class);
        assertThat(user.getName).isEqualTo("bob");
    }
}

Maven依赖:

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.assertj</groupId>
        <artifactId>assertj-core</artifactId>
        <version>1.7.1</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

引发以下StackOverflowException:

Exception in thread "main" java.lang.StackOverflowError
...

// The following lines are repeated.

    at com.fasterxml.jackson.databind.DeserializationContext.readValue(DeserializationContext.java:754)
    at com.fasterxml.jackson.databind.DeserializationContext.readValue(DeserializationContext.java:746)
    at example.UserDeserializer.deserialize(UserDeserializer.java:25)
    at example.UserDeserializer.deserialize(UserDeserializer.java:15)

Process finished with exit code 1

我尝试通过模块注册反序列化程序并删除@JsonAnnotation,但仍然引发相同的异常:

SimpleModule module = new SimpleModule("User Simple Module");
module.addDeserializer(User.class, new UserDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.addModule(module);
mapper.readValue(json, User.class);

然后我尝试在我的UserDeserializer中创建一个新的ObjectMapper,并从我的User类和测试通行证中删除@JsonDeseriize。

@Override
public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    return new ObjectMapper().readValue(p, User.class);
}

在执行上述工作时,我希望使用@JsonDeseriize注释在每个类的基础上注册反序列化器,而不是注册全局自定义对象映射器。我这样想是有原因的。

我尝试了其他代码组合,例如:

// Add the 'as' keyword to the annotation
@JsonDeserialise(using = UserDeserialize.class, as = User.class)

// Locally assigning a mapper from the JsonParser inside the UserDeserializer class
ObjectMapper mapper = (ObjectMapper) p.getCodec();
mapper.readValue(p, User.class);

// Constructing a new JSON Parser inside the deserializer
ObjectMapper mapper = (ObjectMapper) p.getCodec();
JsonFactory factory = mapper.getFactory();
JsonParser parser = factory.createParser(p.getText());
return (User) parser.readValueAs(handledType());

// Reading the Json into a Tree
ObjectMapper mapper = (ObjectMapper) p.getCodec();
ObjectNode root = (ObjectNode) p.readValueAsTree();
return mapper.readValue(root.traverse(), User.class);

但是将JSON读成一棵树会抛出:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalStateException: No ObjectCodec defined for parser, needed for deserialization
    at example.User.main(User.java:46)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.IllegalStateException: No ObjectCodec defined for parser, needed for deserialization
    at com.fasterxml.jackson.core.JsonParser._codec(JsonParser.java:1565)
    at com.fasterxml.jackson.core.JsonParser.readValueAsTree(JsonParser.java:1559)
    at example.UserDeserializer.deserialize(UserDeserializer.java:37)
    at example.UserDeserializer.deserialize(UserDeserializer.java:17)
    at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:3674)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1996)
    at example.UserDeserializer.deserialize(UserDeserializer.java:38)
    at example.UserDeserializer.deserialize(UserDeserializer.java:17)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3702)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2714)
    at example.User.main(User.java:36)
    ... 5 more

我还尝试在我的UserDeserializer中实现上下文解析器,但仍然得到与以前相同的StackOverflow Excema:

private UserDeserializer(Class<?> vc) {
    super(vc);
}

public JsonDeserializer<User> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
    return new UserDeserializer(ctxt.getContextualType().getRawClass());
}

@Override
public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    return (User) new ObjectMapper().readValue(p, handledType());
}

我希望这只是PEBKAC错误的一个糟糕案例,在您的帮助/指导下,可以随时找到解决方案。

问候

共有1个答案

陈俊郎
2023-03-14

我同意KDM,请尝试以下反序列化程序:

    public class UserDeserializer extends JsonDeserializer<User> {

    @Override
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = p.readValueAsTree();
        User user = new User();
        user.setName(node.get("name").asText());
        return user;
    }
}
 类似资料:
  • 我正在开发和android应用程序。我正在使用reverfit(与OkClient一起使用)来处理api请求,并使用Robolectric来进行测试。我的api如下所示: 有人知道问题是什么吗?似乎由于某种未知的原因,线程被杀死了? 多谢了。 编辑:如果在onNext函数(subscribe的第一个参数)中,我执行第二个请求,那么它就工作了。一切都像预期的那样是同步的。 希望这有帮助。

  • 我试图将jBPM 5.4集成到现有的servlet中。 servlet在JBoss 7.1中运行良好,但在我添加一个与jBPM相关的API时,由于抛出异常而失败。(我使用了安装中的评估样本作为模板。)我向servlet的doPost()中添加了: 执行此语句后,将引发以下异常: 20:51:06394错误[org.apache.catalina.core.ContainerBase.[jboss.

  • 问题内容: 编辑:到目前为止,所有建议的答案都没有奏效。 我正在用Django运行此呼叫。服务器第一次运行时,将返回“ n_usr”(这将更改用户文件的形式)。第二次,它只是抛出一个错误。 问题答案: 在中,您具有: 然后您有: 你得到,因为jQuery是试图序列为jQuery对象,而且它不能。它可能正在尝试调用字符串方法,并将其作为上下文传递给jQuery对象,从而导致错误。 您需要添加。

  • 我的主要活动是装载不同的碎片。此外,可以从MainActivity打开设置-activity。 如果用户只是在片段之间切换,那就万事大吉了。 当打开设置-activity并返回MainActivity时,onResume和onPause会被调用两次。如果用户打开设置-activity并再次返回MainActivity,onResume和onPause将被调用三次。每次用户打开“设置-activit

  • 我试图为BillingClient v.2.2.0和Kotlin协同程序编写一个包装: 正如您所见,当我试图查询购买或购买时,我确保客户已经准备好。但在生产中存在许多错误: 我试图了解问题的原因,得到了if将被多次调用。可能存在异常。我一直想知道这是怎么可能的,因为我每次调用都会创建新的侦听器?我无法在emulator或测试设备上重现此问题。有人能解释一下这里发生了什么,以及如何解决吗?

  • 我正在尝试在像这样: 然后在我的它呈现: 我正在将我的fetch记录到控制台中,它被调用了三次。流程是我在登录页面上(加载时挂载一次),我登录,它将我重定向到自己呈现的主页。此时,我在控制台中看到: