2012-08-15 24 views
9

Hy vọng một điều dễ dàng cho các chuyên gia JAXB:XmlJavaTypeAdapter không bị phát hiện

Tôi cố gắng để sắp xếp một lớp học bất biến mà không không xác định một mặc định constructor không-arg. Tôi đã xác định triển khai XmlAdapter nhưng dường như không được chọn. Tôi đã đặt cùng một ví dụ đơn giản khép kín, mà vẫn không hoạt động. Bất cứ ai có thể tư vấn cho những gì tôi đang làm sai?

Immutable Lớp

@XmlJavaTypeAdapter(FooAdapter.class) 
@XmlRootElement 
public class Foo { 
    private final String name; 
    private final int age; 

    public Foo(String name, int age) { 
    this.name = name; 
    this.age = age; 
    } 

    public String getName() { return name; } 
    public int getAge() { return age; } 
} 

Adapter và Loại giá trị

public class FooAdapter extends XmlAdapter<AdaptedFoo, Foo> { 
    public Foo unmarshal(AdaptedFoo af) throws Exception { 
    return new Foo(af.getName(), af.getAge()); 
    } 

    public AdaptedFoo marshal(Foo foo) throws Exception { 
    return new AdaptedFoo(foo); 
    } 
} 

class AdaptedFoo { 
    private String name; 
    private int age; 

    public AdaptedFoo() {} 

    public AdaptedFoo(Foo foo) { 
    this.name = foo.getName(); 
    this.age = foo.getAge(); 
    } 

    @XmlAttribute 
    public String getName() { return name; } 
    public void setName(String name) { this.name = name; } 

    @XmlAttribute 
    public int getAge() { return age; } 
    public void setAge(int age) { this.age = age; } 
} 

marshaller

public class Marshal { 
    public static void main(String[] args) { 
    Foo foo = new Foo("Adam", 34); 

    try { 
     JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class); 
     Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

     // output pretty printed 
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     jaxbMarshaller.marshal(foo, System.out);    
    } catch (JAXBException e) { 
     e.printStackTrace(); 
    } 
    } 
} 

Stack Trace

com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions 
Foo does not have a no-arg default constructor. 
     this problem is related to the following location: 
       at Foo 

     at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91) 
     at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:451) 
     at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:283) 
     at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:126) 
     at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1142) 
     at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:130) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:601) 
     at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248) 
     at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235) 
     at javax.xml.bind.ContextFinder.find(ContextFinder.java:445) 
     at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637) 
     at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:584) 
     at Marshal2.main(Marshal2.java:11) 

Lưu ý rằng tôi đang sử dụng JDK 1.7.0_05.

Trả lời

7

Sau đây sẽ giúp:

FOO AS ROOT OBJECT

Khi @XmlJavaTypeAdapter được quy định ở cấp loại nó chỉ áp dụng cho các lĩnh vực/tài sản tham khảo lớp đó, và không phải khi một thể hiện của lớp đó là một đối tượng gốc trong cây XML của bạn. Điều này có nghĩa là bạn sẽ phải tự chuyển đổi Foo thành AdaptedFoo và tạo JAXBContext trên AdaptedFoo chứ không phải Foo.

Marshal

package forum11966714; 

import javax.xml.bind.*; 

public class Marshal { 
    public static void main(String[] args) { 
     Foo foo = new Foo("Adam", 34); 

     try { 
     JAXBContext jaxbContext = JAXBContext.newInstance(AdaptedFoo.class); 
     Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

     // output pretty printed 
     jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 

     jaxbMarshaller.marshal(new AdaptedFoo(foo), System.out);    
     } catch (JAXBException e) { 
     e.printStackTrace(); 
     } 
    } 
    } 

AdaptedFoo

Bạn sẽ cần phải thêm một chú thích @XmlRootElement đến lớp AdaptedFoo. Bạn có thể xóa cùng một chú thích khỏi lớp Foo.

package forum11966714; 

import javax.xml.bind.annotation.*; 

@XmlRootElement 
class AdaptedFoo { 
    private String name; 
    private int age; 

    public AdaptedFoo() { 
    } 

    public AdaptedFoo(Foo foo) { 
     this.name = foo.getName(); 
     this.age = foo.getAge(); 
    } 

    @XmlAttribute 
    public String getName() { 
     return name; 
    } 

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

    @XmlAttribute 
    public int getAge() { 
     return age; 
    } 

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

FOO AS lồng OBJECT

Khi Foo không phải là đối tượng gốc tất cả mọi thứ hoạt động theo cách bạn có nó ánh xạ. Tôi đã mở rộng mô hình của bạn để chứng minh làm thế nào điều này sẽ làm việc.

Bar

package forum11966714; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Bar { 

    private Foo foo; 

    public Foo getFoo() { 
     return foo; 
    } 

    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 

} 

Demo

Lưu ý rằng việc thực hiện tham khảo JAXB sẽ không cho phép bạn chỉ định các lớp Foo khi bootstrapping các JAXBContext.

package forum11966714; 

import java.io.File; 

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

public class Demo { 
    public static void main(String[] args) { 
     try { 
      JAXBContext jaxbContext = JAXBContext.newInstance(Bar.class); 

      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
      File xml = new File("src/forum11966714/input.xml"); 
      Bar bar = (Bar) jaxbUnmarshaller.unmarshal(xml); 

      Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 
      jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
      jaxbMarshaller.marshal(bar, System.out); 
     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

input.xml/Output

<?xml version="1.0" encoding="UTF-8"?> 
<bar> 
    <foo name="Jane Doe" age="35"/> 
</bar> 
+1

Cảm ơn Blaise! (Tôi nghĩ đó là blog của bạn mà tôi đã xem lúc đầu). Có vẻ như vấn đề là tôi chỉ định Foo.class cho JAXBContext trong quá trình bootstrapping. Xấu hổ JAXB không làm việc tại thời điểm này mà tôi đã chỉ định một bộ chuyển đổi cho Foo ... làm cho bootstrapping một chút fiddly. – Adamski

Các vấn đề liên quan