2014-10-15 3 views
2

내가 지원해야하는 한 프로젝트에서 객체 -> XML -> 객체 프로세스가 있습니다. 개체에 List가 포함되어 있고 직렬화되면 목록에있는 모든 null 값이 생략됩니다. 제 질문은 Simpleframework로 할 수 있습니까, 아니면 다른 것을 사용해야합니까? 뭐?Simpleframework. 컬렉션에 null을 유지할 수 있습니까?

import java.io.StringWriter; 
import java.util.Arrays; 
import java.util.List; 

import org.simpleframework.xml.Attribute; 
import org.simpleframework.xml.ElementList; 
import org.simpleframework.xml.Root; 
import org.simpleframework.xml.core.Persister; 
import org.testng.annotations.Test; 

public class SimpleframeworkTest { 

    @Test 
    public void testNullsInParams() throws Exception { 
     Container container = new Container(); 

     container.setId(4000); 
     container.setParams(Arrays.asList(new Object[] { "foo", null, "bar" })); 

     String xml = container.toXml(); // omits null value in output 
    } 

    @Test 
    public void testDeserializeNull() throws Exception { 
     String xml = "<container id=\"4000\">"+ 
       " <object class=\"java.lang.String\">foo</object>"+ 
//    " <object class=\"java.lang.String\"></object>"+ // gets NullPointerException here 
       " <object class=\"java.lang.String\">bar</object>"+ 
       "</container>"; 
     Container object = Container.toObject(xml); 
    } 

    @Root(name = "container", strict = false) 
    public static class Container { 

     @Attribute 
     private Integer id; 
     @ElementList(inline = true, required = false) 
     private List<Object> params; 

     public String toXml() throws Exception { 
      StringWriter sw = new StringWriter(); 
      new Persister().write(this, sw); 
      return sw.toString(); 
     } 

     public static Container toObject(String xml) throws Exception { 
      return new Persister().read(Container.class, xml); 
     } 

     public Integer getId() { 
      return id; 
     } 
     public void setId(Integer id) { 
      this.id = id; 
     } 
     public List<Object> getParams() { 
      return params; 
     } 
     public void setParams(List<Object> params) { 
      this.params = params; 
     } 

     @Override 
     public String toString() { 
      return "Container [id=" + id + ", params=" + params + "]"; 
     } 
    } 
} 

답변

1

첫째, 목록 주석이 누락 된 항목 이름 :

@ElementList(inline = true, required = false, entry = "object") 
private List<Object> params; 

그렇지 않으면 <string>...</string><object>...</object>가 아닌 사용을 여기 내가 할 것입니다.
목록의 주석에 type = String.class을 추가하여 해당 nullpointer를 방지 할 수 있습니다. 그러나 이것은 주요한 문제를 해결하지 못합니다.

일반적으로 빈 태그/null - 요소는 결과에 추가되지 않습니다.


는 여기 Converter와 함께이 문제를 해결하는 방법을 예입니다.

public class SimpleframeworkTest 
{ 
    // ... 

    @Root(name = "container", strict = false) 
    @Convert(NullawareContainerConverter.class) 
    public static class Container 
    { 
     static final Serializer ser = new Persister(new AnnotationStrategy()); 

     // ... 

     public String toXml() throws Exception 
     { 
      StringWriter sw = new StringWriter(); 
      ser.write(this, sw); 
      return sw.toString(); 
     } 

     public static Container toObject(String xml) throws Exception 
     { 
      return ser.read(Container.class, xml); 
     } 

     // ... 
    } 


    static class NullawareContainerConverter implements Converter<Container> 
    { 
     final Serializer ser = new Persister(); 

     @Override 
     public Container read(InputNode node) throws Exception 
     { 
      final Container c = new Container(); 
      c.id = Integer.valueOf(node.getAttribute("id").getValue()); 
      c.params = new ArrayList<>(); 
      InputNode n; 

      while((n = node.getNext("object")) != null) 
      { 
       /* 
       * If the value is null it's added too. You also can add some 
       * kind of null-replacement element here too. 
       */ 
       c.params.add(n.getValue()); 
      } 

      return c; 
     } 

     @Override 
     public void write(OutputNode node, Container value) throws Exception 
     { 
      ser.write(value.id, node); 

      for(Object obj : value.params) 
      { 
       if(obj == null) 
       { 
        obj = ""; // Set a valid value if null 
       } 
       // Possible you have to tweak this by hand 
       ser.write(obj, node); 
      } 
     } 

    } 

} 

의견에 기록 된대로 추가 작업을해야합니다.

결과 :

testNullsInParams()

<container> 
    <integer>4000</integer> 
    <string>foo</string> 
    <string></string> 
    <string>bar</string> 
</container> 

testDeserializeNull()

Container [id=4000, params=[foo, null, bar]]