2016-11-22 4 views
0

У меня проблемы с доступом к полям немаршаллированных XML-файлов, которые содержат необязательные теги. Вот простой пример, который я сделал для более сложного случая:Java - JAXB XML unmarshal с необязательными полями

<people> 
    <persons> 
     <person> 
      <id>222</id> 
      <pets> 
       <pet> 
        <name age="2">Harry</name> 
       </pet> 
       <pet> 
        <name>Tiffany</name> 
       </pet> 
      </pets> 
     </person> 
     <person> 
      <id>111</id> 
      <pets> 
       <pet value="1"></pet> 
      </pets> 
      <spouse>Frank</spouse> 
     </person> 
    </persons> 
</people> 

Обратите внимание, что второй человек имеет супругу и первый не делает. Кроме того, у домашних животных первого человека есть имена, а у домашних животных второго нет. У домашнего животного по имени Гарри также есть возрастный атрибут. Я пытаюсь показать, что мои XML-файлы могут иметь разные данные из-за необязательных полей.

Вот мои классы моделей для JAXB:

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class People { 

    @XmlElementWrapper 
    @XmlElement(name="person") 
    private List<Person> persons; 

    public List<Person> getPersons() { 
     return persons; 
    } 

    public void setPersons(List<Person> persons) { 
     this.persons= persons; 
    } 

} 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Person { 

    @XmlElement 
    private int id; 

    @XmlElementWrapper 
    @XmlElement(name="pet") 
    private List<Pet> pets; 

    @XmlElement 
    private String spouse; 

    //getters and setters 

} 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class pet { 

    @XmlAttribute 
    private int age; 

    @XmlValue 
    private String name; 

    //getters and setters 

} 

Теперь, давайте скажем, что я просто хочу, чтобы напечатать все имена домашних животных.

for (Person person : people.getPersons()) { 
    for (Pet pet : person.getPets()) { 
     System.out.println("Pet name: " + pet.getName()); 
    } 
} 

Я получаю NullPointerException, если внутренний тег отсутствует. Интересно достаточно, хотя, если вы просто искать поле в слое людей, он просто будет пропускать XML-тег, как если бы он не существует, как:

for (Person person : people.getPersons()) { 
    System.out.println("Spouse: " + person.getSpouse()); 
} 

Эта команда работает даже при том, что первый человек не иметь супруга. Он просто предоставляет строку «null», которая хорошо работает для меня.

Решение, которое я пробовал, - обернуть каждое поле в операторе if или try-catch (я не хочу этого делать, поскольку есть сотни тегов XML). Дайте мне знать, если у вас есть предложения. Благодарю.

+0

Отсутствует большое количество аннотаций XML. Кроме того, первые два примера одинаковы. Кроме того, 'people.getPerson(). Get (i) .getPet.getName' не имеет смысла, так как' getPet' является методом и возвращает список? – thatguy

+0

Ваш XML-пример может быть неправильным, потому что '' не включает '', а 'Dog' и' Cat'. – thatguy

+0

Вы правы, я извиняюсь, если это был плохой пример, но я просто сделал это на лету, чтобы проиллюстрировать простой пример. Эти поля можно заменить чем угодно. Что касается .get (i), я обновляю сообщение, чтобы включить цикл for. Благодарю. – rj2700

ответ

1

NullPointerException в вашем примере вполне очевидно.

System.out.println("Pet name: " + people.getPerson().get(i).getPet().getName()); 

Проблема заключается в том, когда у вас нет домашних животных, getPet() возвращает null. Впоследствии вы вызываете getName() на null, поэтому вы получаете исключение. В вашем втором примере выполнение не происходит, потому что getSpouse() возвращает null, но System.out.println(...) преобразует его в строку null автоматически.

Несмотря на то, что это может показаться утомительным, вам нужно будет явно проверить свои атрибуты для null, когда вы пересекаете свои списки или поля. Никогда сделать это с try-catch! Обработка исключений - это тяжелый механизм, и вы не должны злоупотреблять этой концепцией для проверок null.

+0

Спасибо за ваш ответ! Мой худший страх сбылся, я полагаю, проверяя все поля, чтобы увидеть, являются ли они нулевыми или нет. Но разве эта плохая практика не создает кучу операторов if для каждого поля? Любой возможный способ создать отдельный метод, который проверяет это? – rj2700

+0

Проблема в том, что ваши поля не являются обязательными.В случае, если поле _required_, вы можете их аннотировать, поэтому JAXB проверяет поля и вызывает ошибку на 'null'. Однако, если поля являются необязательными, вы в основном говорите: я ожидаю конкретное значение («объект! = Нуль») или «нуль», оба являются ** действительными ** ввод. Как и в любом другом приложении, вы обрабатываете эти данные в своей логике программы, которая включает проверку «null». Что вы подразумеваете под «созданием множества операторов if для каждого поля»? Что вы на самом деле хотите достичь этим? – thatguy

+0

Что я подразумевал под «созданием множества if-statement», является wrapping if-statements, чтобы увидеть, являются ли теги XML под «person» нулевыми или нет. Поэтому, если он равен нулю, его можно пропустить. Это необходимо для захвата всех полей данных в XML. Что вы * подразумеваете под «проверкой [всех] атрибутов явно для null»? – rj2700

Смежные вопросы