2010-03-16 6 views
4

XStream의 JavaBeanConverter를 사용하려고 시도하고 문제가 발생했습니다. 대부분 나는 뭔가 간단하거나, XStream의 변환기 처리를 충분히 이해하지 못하고 있습니다. XStream JavaBeanConverter가 속성을 serialize하지 않습니다.

@XStreamAlias("test") 
public class TestObject 
{ 
    private String foo; 

    public String getFoo() 
    { 
     //return foo; -- Adjusted for EDIT#2 
     return foo.toLowerCase(); 
    } 

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

public void test() throws Exception 
{ 
    XStream x = new XStream(new XppDriver()); 
    x.autodetectAnnotations(true); 
    x.processAnnotations(TestObject.class); 

    x.registerConverter(new JavaBeanConverter(x.getMapper())); 

    TestObject o = new TestObject(); 
    //o.setFoo("bar"); -- Adjusted for EDIT#2 
    o.setFoo("BAR"); 

    String xml = x.toXML(o); 

    System.out.println(xml); 

    /* 
     Expecting... 
     <test> 
      <foo>bar</foo> 
     </test> 

     But instead getting... 
     <test> 
      <foo/> 
     </test>   
    */ 
} 

는 I는 TestObject.getFoo() 방법에 트레이스를 추가하는 시도하고 그것이 XStream에 의해 호출되는 것으로 나타나지만 데이터 출력 스트림에 기록되지 않는다.

JavaBeanConverter의 소스를 살펴본 후 내 구현이 제대로 작동하는 것처럼 보입니다. 따라서 XStream 설정 중에 올바르게 구성되지 않았다고 생각됩니다.

나는 간단한 것을 놓치고 있습니까?

감사합니다. 도움이된다면


또한 편집 한

, 나는

<dependency> 
    <groupId>org.apache.servicemix.bundles</groupId> 
    <artifactId>org.apache.servicemix.bundles.xstream</artifactId> 
    <version>1.3_3</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.servicemix.bundles</groupId> 
    <artifactId>org.apache.servicemix.bundles.xpp3</artifactId> 
    <version>1.1.4c_3</version> 
</dependency> 


편집 ...이를 위해 다음과 같은 메이븐 deps를 사용하고 2

나는 내 목표를 더 잘 설명하기 위해 TestObject.getFoo() 방법을 변경했다.

getters/setters를 사용하여 내부 객체의 데이터를 "위생"하려고합니다. 특히 Serializable의 readResolve() 메서드를 구현하지 않아도되도록 직렬 리다이렉트 된 데이터를 정리하려고합니다.

readResolve의 메서드를 구현 한 경우 setter 메서드 (다른 deserialized 들어오는 데이터 집합에 대해)와 readResolve (비 직렬화 된 XML 데이터)에서 모두 정리해야합니다.

그 이유는 XStream의 일반 필드 기반 사례 대신 JavaBeanConverter를 사용하여 getters/setters를 통해 데이터를 강제 적용하는 이유입니다.

이 정보가 조금 더 잘 설명되기를 바랍니다.

감사합니다. 당신이 그것을 잘 작동 라인

x.registerConverter(new JavaBeanConverter(x.getMapper())); 

을 주석 경우

+0

좋은 코드 샘플을 보려면 +1 (maven pom snippets) –

답변

4

XStream의 소스를 살펴보면 com.thoughtworks.xstream.core.DefaultConverterLookup에서 확인할 수 있습니다. 당신은 문자열을 알 수

public Converter lookupConverterForType(Class type) { 
    Converter cachedConverter = (Converter) typeToConverterMap.get(type); 
    if (cachedConverter != null) return cachedConverter; 
    Iterator iterator = converters.iterator(); 
    while (iterator.hasNext()) { 
     Converter converter = (Converter) iterator.next(); 
     if (converter.canConvert(type)) { 
      typeToConverterMap.put(type, converter); 
      return converter; 
     } 
    } 
    throw new ConversionException("No converter specified for " + type); 
} 

그것은 JavaBeanConverter을 반환하고 이유는 그 JavaBeanConverter (문자열이) 기본 공용 생성자와 개체에 사용될 것입니다 않습니다.

이 문제를 해결하는 한 가지 방법은 JavaBeanConverter의 우선 순위를 낮추는 것입니다. 그런 다음 JavaBeanConverter이 콩과 SingleValueConverterWrapper에 사용되는

x.registerConverter(new JavaBeanConverter(x.getMapper()), -10); 

은 문자열 값에 사용됩니다.

+0

안녕 랜디, 정보 주셔서 감사합니다. 내 최종 목표를보다 잘 반영 할 수 있도록 원래 질문을 업데이트했습니다. 이 권리를 읽으면, 반대쪽을 시도하고 XStream이 getters/setter (예 : JavaBeanConverter를 통해)를 사용하도록합니다. 그것들 모두가 의미가 있습니까? (나는 때때로 설명하는 것이별로 좋지 않다.) –

+0

나는 위와 같은 생각을한다. 코드를 변경하면 getter가 호출되는 것을 볼 수 있습니다. 문제는 첫 번째 XStream이 TestObject를 마샬링하려고 시도하고 JavaBeanConverter 클래스를 사용하여이를 확인한 다음 getter를 호출하고 String ("bar")을 가져와 이제 해당 String을 마샬링해야한다는 것입니다. String에는 기본 공용 생성자가 있으므로 XStream은 JavaBeanConverter를 다시 사용할 수 있다고 생각하지만 그렇게해서는 안됩니다. 대신 SingleValueConverterWrapper를 사용하여 String을 마샬링해야합니다. XStream 소스를 연결하고 단계별로 살펴 봅니다. –

+0

그래, 네 말이 맞아. 완벽하게 작동합니다. 또한 언 마샬링 (예 : setter를 사용하는 XML)에서 작동합니다. –

2

는 : 나는 그들 중 하나가 충분히 될 때 모두 주석 처리를하고 변환기를 등록하는 생각

http://x-stream.github.io/annotations-tutorial.html

+0

안녕하세요, 원본 질문을 업데이트하여 달성하고자하는 내용을 더 잘 설명했습니다. 미리 최종 목표를 설명하지 않아서 미안합니다. –

관련 문제