Jax-b слишком много интерпретирует - PullRequest
2 голосов
/ 24 октября 2011

У меня есть логическое поле с именем a и два метода void setA(String a) и boolean isA(). Я установил @XmlAccessorType(XmlAccessType.NONE) и использовал @XmlAttribute для сеттера.

Поскольку получатель возвращает логическое значение, но установщик ожидает, что строка JAX-B просто игнорирует этот установщик. Это является причиной всех видов ошибок в коде, потому что логические значения не установлены правильно и отладка, которая очень раздражает.

Есть ли способ указать JAX-B использовать сеттер? Почему JAX-B смущает метод getter, хотя я использую XmlAccessType.NONE, чтобы предотвратить все эти неявные интерпретации?

План B будет состоять в том, чтобы JAX-B потерпел неудачу, если появится такое созвездие, но как это можно сделать?

Благодарен за любую подсказку: -)

Ответы [ 2 ]

3 голосов
/ 24 октября 2011

Учитывая, что вы уже используете аннотацию XmlAccessorType, я думаю, вы уже знаете, что вы можете использовать @XmlAccessType.FIELD и иметь JAXB, чтобы смотреть на поля класса, а не на методы установки, когда решаете, что нужно маршалировать / демаршировать?

С вашей текущей конфигурацией у вас предположительно есть аннотация @XmlElement о методе установки, где тип данных неправильный, как упомянул комментатор.Из вашего вопроса непонятно, зачем вам setA принимать строковый, а не логический параметр, но если вы можете изменить тип на логический в установщике, то это тоже работает.

РЕДАКТИРОВАТЬ:

На основена ваш комментарий ниже, кажется, у вас есть два варианта:

Напишите @XmlAdapter или

Создайте пару setter / getter для строкового поля и isA, который является полем вычисления(так я всегда делал, потому что это кажется немного более простым):

String a;

void setA(String);
String getA();

// calcualted field:
boolean isA() {
    // or whatever your real implementation is
    return a.equals("yes"); 
}
2 голосов
/ 24 октября 2011

Я бы рекомендовал использовать @XmlAccessType.FIELD в соответствии с предложением Кевина в сочетании с XmlAdapter, чтобы получить поведение, которое вы ищете:

Root

Чтобы этот пример работал с JAXB-RI, мне нужно создать поле типа Boolean.Если вы используете EclipseLink JAXB (MOXy) , тогда вы можете сделать поле boolean.

package forum7876493;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class Root {

    @XmlAttribute
    @XmlJavaTypeAdapter(BooleanAdapter.class)
    private Boolean a;

    public boolean isA() {
        return a;
    }

    public void setA(String s) {
        this.a = "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

}

BooleanAdapter

XmlAdapter здесь вы можете добавить логику, которая есть в вашем методе setA(String).

package forum7876493;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class BooleanAdapter extends XmlAdapter<String, Boolean> {

    @Override
    public Boolean unmarshal(String s) throws Exception {
        return "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

    @Override
    public String marshal(Boolean b) throws Exception {
        if(b) {
            return "yes";
        }
        return "no";
    }

}

Демо

package forum7876493;

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Root root = (Root) unmarshaller.unmarshal(new File("src/forum7876493/input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

input.xml

<?xml version="1.0" encoding="UTF-8"?>
<root a="on"/>

Выход

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root a="yes"/>

ОБНОВЛЕНИЕ

В качестве альтернативы вы можете ввести String геттер дляa свойство.Вам нужно сделать метод isA() как @XmlTransient:

package forum7876493;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

@XmlRootElement
public class Root {

    private boolean a;

    @XmlTransient
    public boolean isA() {
        return a;
    }

    @XmlAttribute
    public String getA() {
        if(a) {
            return "yes";
        }
        return "no";
    }

    public void setA(String s) {
        this.a = "yes".equals(s) || "on".equals(s) || "in".equals(s);
    }

}
...