2017-04-10 4 views
0

에서 클래스를 생성합니다. 이 프록시 클래스의 객체를 XML로 쉽게 직렬화 할 수 있습니다. 그러나 XML을 deserialize하려고 시도 할 때 JAXB는 추상 클래스의 인스턴스를 만들 수 없기 때문에 javax.xml.bind.UnmarshalException: Unable to create an instance of A을 던집니다. deserialize하기 위해 런타임에서 이러한 인스턴스를 생성하는 방법을 보여주고 싶습니다. (특별한 Spring bean이 있습니다. 그래서 생성 로직을 정의 할 때마다 주입 할 수 있어야합니다.) JAXB와 Jackson을 보았습니다. , 그러나 그것을하는 방법을 찾을 수 없었다.역 직렬화 XML을 동적으로이 같은 추상 클래스의 집합이 자바

할 방법이 있습니까? 필자는 JAXB 또는 Jackson과 함께 지내는 것이 바람직하지만 모든 직렬화 프레임 워크에 구속되지 않습니다.

+0

샘플 xml을 표시 할 수 있습니까? – Ishnark

답변

0

JAXB와 Jackson이 모두이를 수행 할 수 있음을 발견했습니다.

JAXB는 팩토리 메서드와 어댑터라는 두 가지 방법으로 해결합니다.

@XmlType(factoryClass = MyFactory.class, factoryMethod = "createMyObject") 
public abstract class MyObject { 
    ... 
} 
:

public class MyFactory { 
    public static MyObject createMyObject() { 
     return SomeMagic.createMyObject(); 
    } 
} 

그럼 난 단지 @XmlType 주석을 내 추상 클래스를 표시해야합니다

  1. 사용 JAXB 팩토리 메소드, 나는 객체 생성에 대한 책임을 질 것입니다 공장을 만들어야합니다

  2. JAXB 어댑터를 사용하려면 JAXB에서 인스턴스화하고 XML로 채울 수있는 Java 클래스를 만들어야합니다. 사람에 대한 이러한 클래스의 ERT 오브젝트는 내가 필요

    public class MyAdapter extends XmlAdapter<MyAdapter.MyJaxbObject, MyObject> { 
        @Override 
        public MyObject unmarshal(MyJaxbObject src) throws Exception { 
         MyObject tgt = SomeMagic.createMyObject(); 
         BeanUtils.copyProperties(tgt, src); 
         return tgt; 
        } 
    
        @Override 
        public MyObject marshal(MyObject src) throws Exception { 
         MyJaxbObject tgt = new MyJaxbObject(); 
         BeanUtils.copyProperties(tgt, src); 
         return tgt; 
        } 
    
        public static class MyJaxbObject { 
         ... 
        } 
    } 
    

    그럼 @XmlJavaAdapter 주석 내 추상 클래스를 표시 할 것입니다 :

    @XmlJavaAdapter(MyAdapter.class) 
    public abstract class MyObject { 
        ... 
    } 
    
  3. 잭슨이 내 추상 클래스에 대한 사용자 정의 디시리얼라이저를 만들 수 있습니다 사용. 나는 또한 수행해야

    1. : 때문에, 내 목적 내가 잭슨 정의 디시리얼라이저를 선호 들어

      ObjectMapper mapper = new XmlMapper(); 
      SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null, null, null)); 
      module.addDeserializer(MyObject.class, new MyObjectDeserializer()); 
      mapper.registerModule(module); 
      

    :

    public class MyObjectDeserializer extends StdDeserializer<MyObject> { 
        public MyObjectDeserializer() { 
         super(MyObject.class); 
        } 
    
        @Override 
        public MyObject deserialize(JsonParser parser, DeserializationContext context) throws IOException { 
         ObjectMapper mapper = (ObjectMapper) parser.getCodec(); 
         MyObject myObject = SomeMagic.createMyObject(); 
         return mapper.readerForUpdating(myObject).readValue(parser); 
        } 
    } 
    

    나중에 내 코드에서 나는 내 디시리얼라이저를 등록해야 필드가 채워졌지만이 객체를 다른 객체의 설정자에게 전달하기 전에 중첩 된 객체에 대한 추가 작업 (JAXB는 지원하지 않는 것 같습니다.) t)

  4. 개체 필드를 채울 때 사용자 지정 논리를 사용할 수 있습니다 (어댑터에서도 가능).
  5. 디시리얼라이저를 직접 만들 수 있으므로 종속성 주입을 사용하여 구성 할 수 있습니다 (팩토리는 정적이고 어댑터는 JAXB에서 생성됨).