2012-05-02 9 views
4

Jersey RESTful APIを通じて公開したいクラスがあります。それは次のようになります。JAXBを使用したJersey RESTful APIのJSON出力にヌル要素を含む

@XmlRootElement 
public class Data { 
    public String firstName; 
    public String lastName; 
} 

私の問題は、フィールドがJSON出力から省略された場合には、これらのフィールドがnullになることもあるということです。私はすべてのフィールドがその価値に関係なく存在することを望みます。 lastNameのがnullの場合、例えば、JSONの出力は次のようになります。代わりに私が何をしたいの

{ 
    "firstName" : "Oleksi" 
} 

{ 
    "firstName" : "Oleksi", 
    "lastName" : null 
} 

私はこのようになりますJAXBContextResolver(ContextResolverの実装)があります

@Provider 
public class JAXBContextResolver implements ContextResolver<JAXBContext> { 

    // internal state 
    private final JAXBContext context;  
    private final Set<Class> types; 
    private final Class[] cTypes = { Data.class }; 


    public JAXBContextResolver() 
    throws Exception { 

     types = new HashSet(Arrays.asList(cTypes)); 
     context = new JSONJAXBContext(JSONConfiguration.natural().humanReadableFormatting(true).build(), cTypes); 
    } 

    @Override 
    public JAXBContext getContext(Class<?> objectType) { 

     return (types.contains(objectType)) ? context : null; 
    } 
} 

私はその出力をしばらく取得する方法を見つけようとしていましたが、運がなかったのです。私は他のContextResolvers /シリアライザを試してみたいと思っていますが、動作するものを見つけることができませんでしたので、コード例がうまくいくはずです。

答えて

10

EclipseLink JAXB (MOXy)のJSONバインディングの場合、正しいマッピングは次のようになります。あなたはそれがまたうまくいくかどうかを確認するために、プロバイダでそれを試みることができる:

@XmlRootElement 
public class Data { 
    @XmlElement(nillable=true) 
    public String firstName; 

    @XmlElement(nillable=true) 
    public String lastName; 
} 

詳細情報


UPについてDATE 2

のEclipseLink 2.4は、あなたが

UPDATE 1

を結合MOXYのJSONを活用するために直接使用することができますMessageBodyReader/MessageBodyWriterの実装であるMOXyJsonProviderを含み以下は、MessageBodyReader/MessageBodyWriter

import java.io.*; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.*; 
import javax.xml.transform.stream.StreamSource; 

import javax.ws.rs.*; 
import javax.ws.rs.core.*; 
import javax.ws.rs.ext.*; 
import javax.xml.bind.*; 

import org.eclipse.persistence.jaxb.JAXBContextFactory; 

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(MediaType.APPLICATION_JSON) 
public class MOXyJSONProvider implements 
    MessageBodyReader<Object>, MessageBodyWriter<Object>{ 

    @Context 
    protected Providers providers; 

    public boolean isReadable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public Object readFrom(Class<Object> type, Type genericType, 
      Annotation[] annotations, MediaType mediaType, 
      MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
      throws IOException, WebApplicationException { 
      try { 
       Class<?> domainClass = getDomainClass(genericType); 
       Unmarshaller u = getJAXBContext(domainClass, mediaType).createUnmarshaller(); 
       u.setProperty("eclipselink.media-type", mediaType.toString()); 
       u.setProperty("eclipselink.json.include-root", false); 
       return u.unmarshal(new StreamSource(entityStream), domainClass).getValue(); 
      } catch(JAXBException jaxbException) { 
       throw new WebApplicationException(jaxbException); 
      } 
    } 

    public boolean isWriteable(Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    public void writeTo(Object object, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, Object> httpHeaders, 
     OutputStream entityStream) throws IOException, 
     WebApplicationException { 
     try { 
      Class<?> domainClass = getDomainClass(genericType); 
      Marshaller m = getJAXBContext(domainClass, mediaType).createMarshaller(); 
      m.setProperty("eclipselink.media-type", mediaType.toString()); 
      m.setProperty("eclipselink.json.include-root", false); 
      m.marshal(object, entityStream); 
     } catch(JAXBException jaxbException) { 
      throw new WebApplicationException(jaxbException); 
     } 
    } 

    public long getSize(Object t, Class<?> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType) { 
     return -1; 
    } 

    private JAXBContext getJAXBContext(Class<?> type, MediaType mediaType) 
     throws JAXBException { 
     ContextResolver<JAXBContext> resolver 
      = providers.getContextResolver(JAXBContext.class, mediaType); 
     JAXBContext jaxbContext; 
     if(null == resolver || null == (jaxbContext = resolver.getContext(type))) { 
      return JAXBContextFactory.createContext(new Class[] {type}, null); 
     } else { 
      return jaxbContext; 
     } 
    } 

    private Class<?> getDomainClass(Type genericType) { 
     if(genericType instanceof Class) { 
      return (Class<?>) genericType; 
     } else if(genericType instanceof ParameterizedType) { 
      return (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0]; 
     } else { 
      return null; 
     } 
    } 

} 
+0

私はこれを試しましたが、うまく動作しません。上記以外のコード変更が必要な場合は、詳細をお知らせください。たとえば、JAXBContextResolverクラスを変更する必要がありますか? – Oleksi

+0

私はこのプロジェクトに必要な依存関係をダウンロードすることも困難でした。この文書を無駄に見てみました。 http://wiki.eclipse.org/EclipseLink/Maven – Oleksi

+0

ここにpom.xmlの例を示します。https://github.com/bdoughan/blog20110819/blob/master/pom。xml –

0

JavaScriptは未定義です。 JavaのnullをJavaScriptのnullに変換する場合は、変換ライブラリを参照する必要があります。

関連する問題