Невозможно десериализовать пустое содержимое в тегах при выполнении новой строки

#java #xml #jackson #deserialization #newline

#java #xml #джексон #десериализация #новая строка

Вопрос:

Есть следующие 2 класса:

 @Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Structure {
    @JacksonXmlProperty
    private Info info;


@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@NoArgsConstructor
@AllArgsConstructor
public class Info{
    private Subinfo subinfo;
}
  

выполнение десериализации, как:

  private static final XmlMapper XML_MAPPER = new XmlMapper();
 Structure structure = XML_MAPPER.readValue(input, Structure.class);
  

где input мой XML (см. Ниже)

получено исключение:

 com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.models.Info` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('

    ')
  

эта функция Джексона не помогла:

 XML_MAPPER.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
  

мой XML, который не удался:

 <?xml version='1.0' encoding='UTF-8' ?>
  <Structure>
    <Info>

    </Info>
  </Structure>
  

для этого десериализация XML работает нормально:

 <?xml version='1.0' encoding='UTF-8' ?>
  <Structure>
    <Info/>
  </Structure>
  

Проблема заключается в подходе к закрытию тега:
<Info/> против <Info></Info>

<Info/> работает нормально, пока

 <Info>

 </Info>
  

вызывает исключение при возникновении прерывателей строки

Комментарии:

1. <Info/> является пустой строкой. <Info></Info> является пустой строкой. <Info> </Info> это не пустая строка, поскольку она состоит из пробельных символов. В вашем примере он, похоже, состоит из символа завершения строки ( n или rn , в зависимости от ОС) и 4 пробелов.

2. @Andreas вы правы, это мой вклад, проблема в том, что функция DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT здесь не работает

3. Извините, Jackson обрабатывает только пустые строки, а не пустые строки. Если вам это нужно, вы должны написать некоторую логику десериализации самостоятельно.

4. Не могли бы вы предоставить минимальный git? Мой код работает просто отлично

5. Оба работают нормально @sergionni imgur.com/JicmNj0

Ответ №1:

Как уже упоминали другие в своих комментариях, DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT преобразует только пустые строки в null, но у вас есть пробелы и разделители строк в вашем информационном элементе.

Другие не могут воспроизвести вашу проблему, поскольку вы либо не упомянули, что вы также используете XML_MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true) в своем коде, либо Info в вашем примере XML на самом деле должен быть info, иначе элемент игнорируется.

Для обработки пустых строк и строк, содержащих только пробелы и / или разделители строк, вы можете добавить следующий код перед анализом XML:

 XML_MAPPER.addHandler(new DeserializationProblemHandler() {
    
    @Override
    public Object handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass,
            ValueInstantiator valueInsta, JsonParser p, String msg) throws IOException {
    
      String value = p.getValueAsString();
    
      // ignore "empty" Info elements
      if (instClass.isAssignableFrom(Info.class) amp;amp; (value.isEmpty() || value.matches("[ns] "))) {
        return null;
      }
      return super.handleMissingInstantiator(ctxt, instClass, valueInsta, p, msg);
    }
   
});
  

Если вы хотите сделать это для всех элементов, вы можете просто игнорировать instClass