Hi All,
I have a ContextResolver so that I can use Natural JSON notation:
package com.knowledgemill.rest.main;
import com.knowledgemill.entities.*;
import com.sun.jersey.api.json.JSONJAXBContext;
import com.sun.jersey.api.json.JSONConfiguration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
/*
* This class is used to make sure that when using JSON when an array contains a single
* element it still comes back as an array - makes it much easier to deal with
*/
@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
private Class<?>[] types = {
Artifact.class
, ArtifactPermission.class
, AttachedDoc.class
, AttachedDocArtifact.class
, AuditMessage.class
, Container.class
, ContainerPermission.class
, Context.class
, ContextFolder.class
, Credential.class
, DBLogMessage.class
, EmailArtifact.class
, EmailRecipient.class
, ExtendedAttribute.class
, ExtendedEmail.class
, Group.class
, InternalArtifact.class
, InternalUser.class
, ManagedDocArtifact.class
, StorageTier.class
, SystemAttribute.class
, TreeNode.class
, User.class
, UserEmailAddress.class
};
public JAXBContextResolver() throws Exception {
Map props = new HashMap<String, Object>();
this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
}
public JAXBContext getContext(Class<?> objectType) {
for (Class<?> type : types) {
if (type == objectType) {
return context;
}
}
return null;
}
}
As you can see I have a number of classes which I have specified should be targeted by the this ContextResolver.
Now according to the documentation, the NATURAL configuration should mean that single element arrays will indeed be respected as a array within JSON (instead of returning a single object).
If I take one of my methods which returns List<UserEmailAddress>:
@GET
@Path("user/{userId}/users/{targetUserId}/emailaddresses/")
@Produces({"application/xml","application/json"})
public List<UserEmailAddress> getUserEmailAddresses (@PathParam("userId") String userId
, @PathParam("targetUserId") String targetUserId
) {
List<UserEmailAddress> returnedEmailAddresses = null;
try {
logger.debug("userId value is " + userId);
returnedEmailAddresses = dA.getUserEmailAddresses( targetUserId);
}
catch (Exception e) {
e.printStackTrace();
}
return returnedEmailAddresses;
}
If I exercise this call (using JSON) where it returns multiple elements - I end up with a response shown below:
{"UserEmailAddress": [
{
"userId": "7452272EBA160D9AE040A8C048010EEB",
"smtpAddress": "david.campbell_at_knowledgemill.com",
"primary": "false",
"legacy": "true"
},
{
"userId": "7452272EBA160D9AE040A8C048010EEB",
"smtpAddress": "dcampbell_at_knowledgemill.com",
"primary": "true",
"legacy": "false"
}
]}
This looks good - I can see the array notation in the JSON.
If I exercise this call (using JSON) where it returns a single element - I end up with a response shown below:
{"UserEmailAddress": {
"userId": "7452272EBA160D9AE040A8C048230EEB",
"smtpAddress": "john_at_knowledgemill.com",
"primary": "true",
"legacy": "false"
}}
This is bad - the single element is not coming back as an array.
From my understanding this should have been rectified when using a NATURAL JSON notation. It does not work for me.
I have also tried fixing the arrays specifically with the default MAPPED notation e.g.:
JSONConfiguration.mapped().arrays( NAMES OF ARRAYS HERE).build()
This also does not work.
It appears that the ContextResolver is having no effect. However, I have confirmed that the Provider is being loaded on startup.
Any help - much appreciated.
Cheers.
James