In order to solve the bug in Jersey that fails to serialize correctly a list with (only) one element, to wit:
"list":"thing"
instead of
"list": [ "thing" ]
I've written the code below which very nearly solves it, but (infuriatingly) gives me no way to tell it not to enclose the whole result in double quotes like this:
"list": "[ "thing" ]"
I'm out of options and would thank profusely anyone who sees clearly through this. Note that I've also attempted the ContextResolver< JAXBContext > as a @Provider solution suggested by a couple of posts out there, but Jersey never calls that code at all. This solution is the only one that comes close.
By the way, here's the consuming field in the POJO:
@XmlAnyElement
@XmlJavaTypeAdapter( JaxBListAdapter.class )
private List< String > list = new ArrayList< String >();
And here's the code:
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;
}
}