Бесконечная рекурсия при десериализации с Джексоном и Мокито - PullRequest
0 голосов
/ 05 октября 2018

Я пытаюсь распечатать любой объект с помощью mapper.writeValueAsString, но я сталкиваюсь с бесконечной рекурсией при десериализации объектов с помощью Мокито и Джексона.Объекты, которые я пытаюсь десериализовать, выполняют базовые вызовы Hibernate для БД и т. Д., И я не имею никакого контроля над самими классами.

В настоящее время я использую следующие версии Mockito и Jackson, но то же самое происходит и для старых версий 1.X-версии Джексона.

  • Mockito: org.mockito:mockito-all:jar:1.9.5:compile
  • Джексон: com.fasterxml.jackson.core:jackson-databind:jar:2.9.7:compile

Как указано, я не могу изменять базовые классы с аннотациейтакие как @JsonIgnore, потому что они находятся за пределами зависимостей, не под моим контролем.Я также не могу создавать миксины для своего пользовательского случая, потому что я пытаюсь распечатать содержимое любого отправляемого объекта.

Я пытался добавить 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;
    }
}

Вывод терминала бесконечной рекурсии виден при выполнении тестов Mockito для методов, которые содержат операторы Log4j, которые в свою очередь вызывают функцию PrintUtil.Оператор e.printStackTrace() начинает печатать во время выполнения тестов.

Большинство объектов, отправляемых этому служебному методу, являются объектами ответа службы XML JAXB.

1 Ответ

0 голосов
/ 10 октября 2018

Не имея возможности изменять сами классы, я вижу два возможных решения.

1) Оберните объекты в ваши собственные объекты, как предложено @ TheHeadRush , и соответствующим образом аннотируйте их.Я бы предложил использовать @JsonIdentityInfo, чтобы объекты сериализовались под своим идентификатором, а не игнорировались полностью с @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);
...