2012-08-16 5 views
1

У меня проблема с преобразованием XML в объект Java, здесь я использую JAXB.
в моем случае:Как настроить JAXBContext Unmarshaller для сложного случая

XML DATA:

<persons> 
    <person> 
    <name>Aris Tonar</name> 
    <age /> 
    <nickname /> 
    <saldo /> 
    </person> 
</persons> 

JAVA КЛАСС XML ДАННЫХ:

public class Person{ 
    private String name; 
    private Integer age; 
    private String nickName; 
    private Integer id; 
    private Double saldo; 

    /** 
    *Setter and Getter 
    */ 

} 

и когда я с помощью стандартного кода JAXBContext Unmarshaller для синтаксического анализа на Java Object. с кодом:

JAXBContext context = JAXBContext.newInstance(Person.class.getPackage().getName()); 
Unmarshaller unmarshaller = context.createUnmarshaller(); 
JAXBElement element = (JAXBElement) unmarshaller.unmarshal(new StreamSource(new StringReader(stringOfXmlData.toString()))); 
Person obj = (Person) element.getValue(); 

это даст результат: Person имя = "Арис Тонар"
Person возраст = нуль
Person ник = ""
Person ID = нулевой
Person Saldo = нуль

, но не то, что в результате того, что я хочу, я хочу JAXB даст результат:

Person имя = «Арис Тонар»
Person возраст = 0
Person ник = ""
Person ID = нулевой
Person Saldo = 0

  1. я хочу, чтобы каждый элемент, который объявлен в XML-данных будет: если это значение указано JAXB будет интерпретируя он как обычный (например, элемент name), но если это значение не указано, jaxb будет интерпретировать его как значение по умолчанию (например, возраст, псевдоним, элементы салдо)
  2. и если элемент не объявлен в XML-данных, поэтому jaxb будет интерпретировать его как null. (например, элемент id)

Возможно ли это? может быть с настройкой кода JAXBContext?

ответ

3
@XmlType(name = "person", propOrder = {"name", "age", "nickName" , "saldo"}) 
public class Person { 

private String name; 
private Integer age; 
private String nickName; 
private Integer id; 
private Double saldo; 

public Person(String name, Integer age, String nickName, Integer id, Double saldo) { 
    this.name = name; 
    this.age = age; 
    this.nickName = nickName; 
    this.id = id; 
    this.saldo = saldo; 
} 

public Person() { 
    //jaxb constructor 
} 

@XmlElement(defaultValue="0") 
public Integer getAge() { 
    return age; 
} 

@XmlTransient 
public Integer getId() { 
    return id; 
} 

@XmlElement(defaultValue="") 
public String getName() { 
    return name; 
} 

@XmlElement(name="nickname" , defaultValue="") 
public String getNickName() { 
return nickName; 
} 

@XmlElement(defaultValue="0") 
public Double getSaldo() { 
    return saldo; 
} 

public void setAge(Integer age) { 
    this.age = age; 
} 

public void setId(Integer id) { 
    this.id = id; 
} 

public void setName(String name) { 
    this.name = name; 
} 

public void setNickName(String nickName) { 
    this.nickName = nickName; 
} 

public void setSaldo(Double saldo) { 
    this.saldo = saldo; 
} 


} 
+0

+1 - Вы правы. –

+0

Большое спасибо Err, ваше объяснение - это мое решение ,, –

+0

hallo Err, у меня есть другая проблема .. Мой Java-класс, а также его аннотация xml в этом классе является результатом JAXB Binding из xsd-файла, в моем случае JAXB Binding определяет '@XmlAttribute' для свойства, поэтому как я могу назначить defaultValue для этого свойства. Спасибо, –

1

Если вы создаете экземпляр своих членов со значениями по умолчанию при их объявлении, вы должны исправить первую проблему.

Try:

public class Person{ 
private String name = ""; 
private Integer age = 0; 
private String nickName; = "" 
private Integer id = 0; 
private Double saldo =0.0; 

НТН,
mcalex

0

я использовать CxF-Codegen-плагин, вы можете (начиная с XSD/WSDL)

  1. Настройка вверх по умолчанию значение в XSD вашей модели данных (ключевое слово по умолчанию для каждого типа)
  2. Используйте расширение cxf-xjc-dv для p lugin для обработки значений по умолчанию в геттерах сгенерированных классов.

Это будет, например, создать геттер для вашего поля возраста, как это:

public Integer getAge() { 
    if (age == null) 
     return new Interger(0); 
    return age; 
} 
+0

Это обратное тому, что хочет ОП, хотя, как это будет возвращать значения по умолчанию для элементов, которые _not_, указанных в XML и/нулевых значениях пустой строки для элементов, _are_ указанных, но имеет пустое значение. OP хочет указать-но-пусто -> по умолчанию и неуказано -> 'null'. –

3

Это немного громоздким, но вы должны быть в состоянии добиться того, что вы хотите с помощью адаптеров типа:

public class Person{ 
    private String name; 
    @XmlJavaTypeAdapter(IntegerZeroDefaultAdapter.class) 
    @XmlSchemaType(name = "integer") 
    private Integer age; 
    private String nickName; 
    private Integer id; 
    @XmlJavaTypeAdapter(DoubleZeroDefaultAdapter.class) 
    @XmlSchemaType(name = "double") 
    private Double saldo; 
    // ...  
} 

public class IntegerZeroDefaultAdapter extends XmlAdapter<String, Integer> { 
    public String marshal(Integer n) { 
    return String.valueOf(n); 
    } 

    public Integer unmarshal(String val) { 
    if(val == null) return null; 
    else if("".equals(val)) return 0; 
    else return Integer.valueOf(val); 
    } 
} 

// likewise for DoubleZeroDefaultAdapter 

Вам не нужен адаптер для имени или псевдонима, если значение по умолчанию, которое вы хотите использовать, не является чем-то иным, чем пустая строка. Значение по умолчанию для строковых значений заключается в том, что отсутствующий элемент означает null и заданное-bu t-empty element означает пустую строку, помните, что в XML <nickname /> точно соответствует <nickname></nickname>.

+0

Хотя при повторном чтении документов я бы сказал, что ответ Эрра с использованием '@XmlElement (defaultValue =" ... ")' является лучшим решением. –

+0

Поблагодарите Ian Roberts, хотя ответ Err более прост, но ваше объяснение - это мое решение для сложного элемента handle, такого как java.util.Date или другого не класса-оболочки (Custom Class). –

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