1

(のみ)1つの要素を持つリストを正しくシリアル化できないJerseyのバグを解決するには、次のようにします。

"list":"thing"

それ以外の

"list": [ "thing" ]

私はそれをほぼ解決する以下のコードを書きましたが、(腹立たしいことに)結果全体を次のように二重引用符で囲まないように指示する方法はありません:

"list": "[ "thing" ]"

私には選択肢がなく、これを通してはっきりと見える人には心から感謝します。いくつかの投稿で提案されている@ProviderソリューションとしてContextResolver<JAXBContext>も試しましたが、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 に答える