2013-03-13 1 views
0

Для того, чтобы решить эту ошибку в Джерси, который не правильно сериализации список с (только) один элемент, а именно:Расширение XMLAdapter для обработки ArrayList покрывающей [...] с кавычками

"list":"thing" 

вместо из

"list": [ "thing" ] 

Я написал код, ниже которого почти решает, но (раздражающе) не дает мне никакого способа узнать это не вложить весь результат в двойных кавычках, как это:

"list": "[ "thing" ]" 

У меня нет вариантов, и я буду благодарен всем, кто ясно видит это. Обратите внимание, что я также попытался найти решение, предлагаемое несколькими сообщениями там, но Джерси никогда не вызывает этот код вообще. Это решение единственное, что подходит близко.

Кстати, вот поле потребляющих в POJO:

@XmlAnyElement 
@XmlJavaTypeAdapter(JaxBListAdapter.class) 
private List<String> list = new ArrayList<String>(); 

А вот код:

public class JaxBListAdapter extends XmlAdapter< Element, List<String> > 
{ 
    private static Logger log = Logger.getLogger(JaxBListAdapter.class); 

    private DocumentBuilder documentBuilder = 
        DocumentBuilderFactory.newInstance().newDocumentBuilder(); 

    @Override 
    public Element marshal(List<String> list) 
    { 
     Document document = documentBuilder.newDocument(); 
     Element rootElement = document.createElement("list"); 

     document.appendChild(rootElement); 

     if(list != null) 
     { 
      StringBuilder sb = new StringBuilder(); 

      sb.append("[ "); 

      boolean first = true; 

      for(String item : list) 
      { 
       if(first) 
        first = false; 
       else 
        sb.append(", "); 

       sb.append("\"" + item + "\""); 
      } 

      sb.append(" ]"); 

      rootElement.setTextContent(sb.toString()); 
     } 

     return rootElement; 
    } 

    @Override 
    public List<String> unmarshal(Element rootElement) 
    { 
     // Hmmmm... never callled? 
     NodeList  nodeList = rootElement.getChildNodes(); 
     List<String> list  = new ArrayList<String>(nodeList.getLength()); 

     for(int x = 0; x < nodeList.getLength(); x++) 
     { 
      Node node = nodeList.item(x); 

      if(node.getNodeType() == Node.ELEMENT_NODE) 
       list.add(node.getTextContent()); 
     } 

     return list; 
    } 
} 
+0

Оказывается, что ContextResolver /@ Provider не работает неправильно. Наконец я понял, что мне нужно рассказать об этом Джерси в web.xml. Теперь это работает. Я собираюсь опубликовать это решение здесь как ответ, но не как ответ. Возможно, все равно стоит ответить (или, по крайней мере, poo-pooing) на этот вопрос. –

ответ

0

Я надеюсь, что я не буду никого обижать, разместив эту работу, вокруг которого некоторые могут обвиниться как несвязанные или только косвенно связанные с первоначальным вопросом. Это решение проблемы, которую я пытался решить, используя подход в вопросе. Кто-то, кто смотрит на вопрос по той же причине, может найти это полезным.

В конечном счете, решение с использованием ContextResolver < JAXBContext> works.

Вот мой код:

package com.acme.web.user.pojo; 

import java.util.Arrays; 
import java.util.HashSet; 
import java.util.Set; 

import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.Provider; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 

import com.sun.jersey.api.json.JSONConfiguration; 
import com.sun.jersey.api.json.JSONJAXBContext; 

/** 
* This class will solve lists containing only one member which Jersey doesn't bracket. 
* It ensures the brackets [ ... ] in generated JSON. 
*/ 
@Provider 
public class JaxBContextResolver implements ContextResolver<JAXBContext> 
{ 
    private final JAXBContext context; 

    @SuppressWarnings("rawtypes") 
    private final Set<Class> types; 

    @SuppressWarnings("rawtypes") 
    private final Class[] classTypes = { Account.class }; 

    @SuppressWarnings("rawtypes") 
    public JaxBContextResolver() throws JAXBException 
    { 
     context = new JSONJAXBContext(JSONConfiguration.natural().build(), classTypes); 
     types = new HashSet<Class>(Arrays.asList(classTypes)); 
    } 

    public JAXBContext getContext(Class<?> objectType) 
    { 
     return types.contains(objectType) ? context : null; 
    } 
} 

Но, вы должны добавить пакет web.xml тоже или Джерси не будет искать для этого класса, как @Provider.

<init-param> 
    <param-name>com.sun.jersey.config.property.packages</param-name> 
    <param-value>com.acme.web.user.pojo</param-value> 
</init-param>