扩展XmlAdapter以处理ArrayList用引号括起来

时间:2013-03-13 17:47:56

标签: jaxb jersey xmladapter

为了解决Jersey中无法使用(仅)一个元素正确序列化列表的错误,即:

"list":"thing"

而不是

"list": [ "thing" ]

我已经编写了下面几乎解决它的代码,但是(令人愤怒的)让我无法告诉它不要将整个结果用双引号括起来:

"list": "[ "thing" ]"

我没有选择,并且会非常感谢任何通过此看清楚的人。请注意,我还尝试了 ContextResolver< JAXBContext> 作为 @Provider 解决方案,由几个帖子提出,但泽西从来没有调用过该代码。这个解决方案是唯一接近的解决方案。

顺便说一句,这是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;
    }
}

1 个答案:

答案 0 :(得分:0)

我希望我不会冒犯任何人,因为有些人可能会指责这些工作与原始问题无关或只是倾向于相关。这是我试图用问题中的方法解决的问题的解决方案。出于同样的原因看某个问题的人可能会觉得这很有用。

最终,解决方案使用 ContextResolver&lt; JAXBContext&gt; 有效。

这是我的代码:

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 ,否则Jersey将不会将此类作为 @Provider 进行查找。

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