1

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

"list":"thing"

代替

"list": [ "thing" ]

我已经编写了下面的代码,它几乎可以解决它,但是(真气)让我无法告诉它不要将整个结果用双引号括起来,如下所示:

"list": "[ "thing" ]"

我别无选择,我会非常感谢任何看透这一点的人。请注意,我还尝试将ContextResolver < JAXBContext >作为一些帖子建议的@Provider解决方案,但 Jersey 根本不会调用该代码。此解决方案是唯一接近的解决方案。

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

1 回答 1

0

我希望我不会通过发布这个解决方法来冒犯任何人,有些人可能会指责它与原始问题无关或仅与原始问题有间接关系。这是我试图使用问题中的方法解决的问题的解决方案。出于相同原因查看该问题的人可能会发现这很有用。

最终,使用ContextResolver< JAXBContext >的解决方案有效。

这是我的代码:

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>
于 2013-03-13T18:47:07.697 回答