【问题标题】:Infinite recursion when deserializing with Jackson and Mockito使用 Jackson 和 Mockito 反序列化时的无限递归
【发布时间】:2018-10-05 18:01:15
【问题描述】:

我正在尝试使用mapper.writeValueAsString 一般打印任何对象,但是在使用 Mockito 和 Jackson 反序列化对象时我面临着无限递归。我试图反序列化的对象执行对 DB 等的底层 Hibernate 调用,我无法控制类本身。

目前我正在使用以下版本的 Mockito 和 Jackson,但对于较旧的 Jackson 1.X 版本也是如此。

  • 模拟:org.mockito:mockito-all:jar:1.9.5:compile
  • 杰克逊:com.fasterxml.jackson.core:jackson-databind:jar:2.9.7:compile

正如指定的,我无法使用 @JsonIgnore 等注释修改底层类,因为它们是不受我控制的外部依赖项。我也无法为我的用户案例创建 mixins,因为我试图一般地打印发送的任何对象的内容。

我已尝试在较旧的 Jackson 版本中将 DeserializationConfig FAIL_ON_UNKNOWN_PROPERTIES 添加到 false,并尝试将 DeserializationFeature FAIL_ON_MISSING_CREATOR_PROPERTIES 设置为 false

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public static PrintUtil {
    public static String printJSON(Object obj) {
        String printstring = "printfailed";
        try {
            ObjectMapper mapper = new ObjectMapper();
            LOG.debug("formatted JSON String ");
            printstring = mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return printstring;
    }
}

在对包含 Log4j 语句的方法运行 Mockito 测试时会看到无限递归终端输出,这些语句又调用 PrintUtil 函数。语句 e.printStackTrace() 在运行测试时开始打印。

发送到此实用程序方法的大多数对象是 JAXB XML 服务响应对象。

【问题讨论】:

  • 我看不到mockito在这里的作用是什么?另外,您要序列化的对象是什么?
  • @SergiiBishyr 我已经编辑了我的问题并添加了有关 mockito 和我正在序列化的对象的更多信息。
  • 您可能需要查看@JsonIgnore@JsonIgnoreProperties@JsonManagedReference / @JsonBackReference 组合,看看哪个最适合您的用例。
  • @TheHeadRush 正如我在问题中所述,我无法向传入的对象添加注释,因为它们不归我所有,它们主要是 JAXB XML 对象,它们本质上是底层 C++ 对象的接口。

标签: java hibernate jackson mockito jackson-databind


【解决方案1】:

在无法修改类本身的情况下,我看到了两种可能的解决方案。

1) 按照@TheHeadRush 的建议将对象包装到您拥有的对象中,并对其进行适当的注释。我建议使用@JsonIdentityInfo,以便对象序列化到它们的ID,而不是使用@JsonIgnore 完全忽略。

2) 对导致递归的对象使用自定义反序列化器。这是一个例子:

public class CustomDeserializer extends StdDeserializer<MyObject>{

   // Add constructors as necessary.

    @Override
    public List<Item> deserialize(
      JsonParser jsonparser, 
      DeserializationContext context) 
      throws IOException, JsonProcessingException {
       return null; // Return something that won't recurse here.
    }
}

然后使用您正在使用的ObjectMapper 注册解串器:

// Register the deserializer:
SimpleModule module = new SimpleModule()
    .addDeserializer(MyObject.class, new CustomDeserializer());

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

【讨论】:

    猜你喜欢
    • 2014-05-16
    • 1970-01-01
    • 2015-10-02
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 2019-06-23
    • 2016-12-11
    相关资源
    最近更新 更多