Десериализация вывода PMD с помощью Jackson

#java #xml #jackson #pmd

Вопрос:

Я пытаюсь десериализовать вывод PMD с помощью Jackson. В частности, я хочу получить список нарушений и их данные, которые PMD предоставляет мне в следующей форме:

 <pmd-cpd>
<duplication lines="615" tokens="1188">
<file line="126" path="SomePathHere"/>
<file line="126" path="SomePathHere"/>
<codefragment>
<![CDATA[
SomeCodeFragmentHere
]]>
</codefragment>
</duplication>
MoreDuplications
</pmd-cpd>
 

В настоящее время у меня есть следующие классы для десериализации:

 public class PmdResults {
  @JacksonXmlProperty(localName = "duplication")
  List<CodeClone> codeClones;
}

public class CodeClone {
  public int lines;
  public int tokens;

  @JacksonXmlProperty(localName = "file")
  public List<SourceFile> files;

  public CodeClone() { super(); }
  
  public static class SourceFile {
    public int line;
    public String path;
  }
}
 

В настоящее время Jackson может десериализовать корень и оба «строки» и «токены» правильно. Однако, вместо того, чтобы пытаться десериализовать два элемента «file» в объекты SourceFile, он ищет непосредственно атрибут «line» для десериализации атрибутов этих элементов. Я также не уверен, как заставить Jackson игнорировать элемент «codefragment», учитывая, что мне на самом деле не нужна эта информация. Я был бы очень благодарен за любую помощь в этом отношении, поскольку мне немного сложно понять, почему он смог определить, что дублирующие элементы должны становиться объектами в списке, но не элементами файла, которые, похоже, соответствуют тому же формату.

PS.: На самом деле я бы предпочел вообще избавиться от класса PmdResults и напрямую десериализовать список<CodeClone> , но я также не смог найти какой-либо способ сделать это.

Ответ №1:

В вашем Java-коде есть два типа проблем:


В вашем Java-коде у вас есть свойства типа List<...>

 @JacksonXmlProperty(localName = "duplication")
List<CodeClone> codeClones;
 

и

 @JacksonXmlProperty(localName = "file")
List<SourceFiles> files;
  
 

Вам также нужно аннотировать эти List свойства
с @JacksonXmlWrapper(useWrapping = false) помощью .
Если вы опустите это, то по умолчанию будет useWrapping = true
и Джексон ожидал бы, например

 <file>  
  <file>...</file>
  <file>...</file>
</file>
 

вместо того, чтобы просто

 <file>...</file>
<file>...</file>
 

См . Также документ Java of @JacksonXmlElementWrapper .


В вашем примере XML у вас есть несколько атрибутов XML (например line="126" , or path="SomePathHere" ), которые, конечно, отличаются от элементов XML (например <line>126</line> , or <path>SomePathHere</path> ).

Вам нужно сообщить Jackson, что это атрибуты XML, аннотируя свойство Java с @JacksonXmlProperty(isAttribute = true) помощью . Если вы опустите это, то по умолчанию будет isAttribute = false и Jackson будет ожидать XML-элемент вместо XML-атрибута.

См . Также документ Java of @JacksonXmlProperty .