JAXB编组和泛型 [英] JAXB Marshalling and Generics

查看:514
本文介绍了JAXB编组和泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用JAXB的自省对marshall进行反编译并取消对JAXB注释标记的某些现有域对象的解除。大多数事情都按预期工作,但是我得到一个相当简单的类来序列化时遇到了一些麻烦。这个类在许多bean上用作@XmlElement,看起来像这样:

  public class Range< E extends Comparable< E  - 代替;>实现Serializable {
protected boolean startInclusive,endInclusive;
保护E开始,结束;

public Range(){
startInclusive = endInclusive = true;

$ b $ public boolean contains(E value){...}

public E getEnd(){
return end;
}

public void setEnd(E end){
this.end = end;
}

public boolean isEndInclusive(){
return endInclusive;
}

public void setEndInclusive(boolean endInclusive){
this.endInclusive = endInclusive;
}

public E getStart(){
return start;
}

public void setStart(E start){
this.start = start;
}

public boolean isStartInclusive(){
return startInclusive;
}

public void setStartInclusive(boolean startInclusive){
this.startInclusive = startInclusive;
}
}

我试图做到以下几点,但没有成功,JAXB仍然对Comparable接口感到愤怒。

  public class DoubleRange extends Range< Double> {} 

使用Range和DoubleRange作为bean getter的返回类型会产生如下异常: p>

 
java.lang.Comparable是一个接口,JAXB无法处理接口。
此问题与以下位置有关:
在java.lang.Comparable $ b $ protected at protected java.lang.Comparable com.controlpath.util.Range.start
at example。 util.Range
at example.util.DoubleRange
at public example.util.DoubleRange example.domain.SomeBean.getRange()
at example.domain.SomeBean

我知道在大多数情况下,List< T>和Map< T,U>因为JAXB规范在遇到bean时对这些类型有特殊的规定,但是有什么方法可以传达我想要的JAXB自省引擎,而不必使用非泛型字段来实现范围?

解决方案

通过执行以下操作, p> 1)声明一个接受各种元素并拥有JAXB注释
的类并按照你的意愿处理它们(在我的例子中,我将所有东西都转换为字符串)

  @YourJAXBAnnotationsGoHere 
public class MyAdapter {

@XmlElement //或@XmlAttribute如果您希望
私有字符串内容;
$ b $ public MyAdapter(Object input){
if(input instanceof String){
content =(String)input;
} else if(输入instanceof YourFavoriteClass){
content =((YourFavoriteClass)input).convertSomehowToString();
} else if(input instanceof .....){
content =((.....)input).convertSomehowToString();
//等等
} else {
content = input.toString();
}
}
}

//我建议使用Map< Class<>,IMyObjToStringConverter> ...
//避免讨厌的if-else-instanceof事物



<2>使用这个类而不是E在你要编组的类中



NOTES




  • 当然,这对于复杂的(嵌套的)数据结构是 not

  • 你必须考虑如何解组,可能会更棘手。如果
    太棘手,请等待比我更好的提案;)

    I am trying to use JAXB's introspection to marshall and unmashall some existing domain objects marked up with JAXB annotations. Most things work as expected, but I am having quite a bit of trouble getting a fairly simple class to serialize. This class is used as an @XmlElement on a number of beans and looks something like:

    public class Range<E extends Comparable<E>> implements Serializable {
        protected boolean startInclusive, endInclusive;
        protected E       start, end;
    
        public Range(){
                startInclusive = endInclusive = true;
        }
    
        public boolean contains(E value){...}
    
        public E getEnd() {
                return end;
        }
    
        public void setEnd(E end) {
                this.end = end;
        }
    
        public boolean isEndInclusive() {
                return endInclusive;
        }
    
        public void setEndInclusive(boolean endInclusive) {
                this.endInclusive = endInclusive;
        }
    
        public E getStart() {
                return start;
        }
    
        public void setStart(E start) {
                this.start = start;
        }
    
        public boolean isStartInclusive() {
                return startInclusive;
        }
    
        public void setStartInclusive(boolean startInclusive) {
                this.startInclusive = startInclusive;
        }
    }
    

    I have tried to do the following, with no success, JAXB is still angry with the interface Comparable.

    public class DoubleRange extends Range<Double> {}
    

    Using both Range and DoubleRange as return types for the bean getter's yields an exception like:

    java.lang.Comparable is an interface, and JAXB can't handle interfaces.
        this problem is related to the following location:
            at java.lang.Comparable
            at protected java.lang.Comparable com.controlpath.util.Range.start
            at example.util.Range
            at example.util.DoubleRange
            at public example.util.DoubleRange example.domain.SomeBean.getRange()
            at example.domain.SomeBean
    

    I realize that in most cases List<T> and Map<T, U> only work because the JAXB specification has special provisions for those types when they are encountered on beans, but is there any way to convey what I want to the JAXB introspection engine without having to reimplement range with non-generic fields?

    解决方案

    You could write a custom adapter (not using JAXB's XmlAdapter) by doing the following:

    1) declare a class which accepts all kinds of elements and has JAXB annotations and handles them as you wish (in my example I convert everything to String)

    @YourJAXBAnnotationsGoHere
    public class MyAdapter{
    
      @XmlElement // or @XmlAttribute if you wish
      private String content;
    
      public MyAdapter(Object input){
        if(input instanceof String){
          content = (String)input;
        }else if(input instanceof YourFavoriteClass){
          content = ((YourFavoriteClass)input).convertSomehowToString();
        }else if(input instanceof .....){
          content = ((.....)input).convertSomehowToString();
        // and so on
        }else{
          content = input.toString();
        }
      }
    }
    
    // I would suggest to use a Map<Class<?>,IMyObjToStringConverter> ...
    // to avoid nasty if-else-instanceof things
    

    2) use this class instead of E in your to-be-marshalled class

    NOTES

    • Of course this would not work for complex (nested) data structures.
    • You have to think how to unmarshall this back again, could be more tricky. If it's too tricky, wait for a better proposal than mine ;)

    这篇关于JAXB编组和泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆