2013-03-06 106 views
2

我有一個用例,我需要維護兩組JSON輸出,一個帶有JSON屬性的漂亮名稱,另一個沒有。所以我決定自定義我的ObjectMapper,以便它忽略字段上的@JsonProperty(「漂亮名稱」)註釋並使用字段屬性名稱。在這種情況下,需要以下JSON輸出自定義傑克遜對象映射器

{"result":{"data":[{"totalUsers":12345,"totalBooks":883}]}} 

漂亮的名字想喜歡的JSON輸出如下

{"result":{"data":[{"Total Users":12345,"Total Books":883}]}} 

我ObjectMapper配置代碼看起來像

ObjectMapper mapper = new ObjectMapper(); 
mapper.setSerializationInclusion(Include.NON_EMPTY); 
mapper.setSerializationInclusion(Include.NON_NULL); 
mapper.configure(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME, true); 
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); 
mapper.configure(MapperFeature.USE_ANNOTATIONS, false); 
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.NONE) 
     .setVisibility(PropertyAccessor.GETTER, Visibility.ANY); 

我已經看過還有一些其他的答案對我來說不起作用。我得到一個NPE。請看下面的堆棧跟蹤

java.lang.NullPointerException 
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._renameWithWrappers(POJOPropertiesCollector.java:728) 
at com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collect(POJOPropertiesCollector.java:264) 
at com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.collectProperties(BasicClassIntrospector.java:142) 
at com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.forSerialization(BasicClassIntrospector.java:68) 
at com.fasterxml.jackson.databind.introspect.BasicClassIntrospector.forSerialization(BasicClassIntrospector.java:11) 
at com.fasterxml.jackson.databind.SerializationConfig.introspect(SerializationConfig.java:490) 
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:131) 
at com.fasterxml.jackson.databind.ser.SerializerFactory.createSerializer(SerializerFactory.java:53) 
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:935) 
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:892) 
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:429) 
at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:520) 
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:99) 
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:457) 
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.writeTo(JacksonJsonProvider.java:583) 
at org.apache.cxf.jaxrs.utils.JAXRSUtils.writeMessageBody(JAXRSUtils.java:1173) 
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:259) 
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:155) 
at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:86) 
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) 
at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77) 
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:271) 
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) 
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:238) 
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:222) 
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:163) 
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:137) 
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:158) 
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:239) 
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:164) 

的問題是在這行代碼在

com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._renameWithWrappers(POJOPropertiesCollector.java:728) 

其中_annotationIntrospector爲空

PropertyName wrapperName = _annotationIntrospector.findWrapperName(member); 

不太疼我應該怎麼做才能acheieve我目標。有什麼建議?謝謝。

+1

只是一個想法:你有沒有考慮使用mixin的註解漂亮打印JSON呢? (也許我明天有時間看看你的實際問題。) – nutlike 2013-03-06 19:42:32

+0

我做了一個簡短的測試,顯然是'mapper.configure(MapperFeature.USE_ANNOTATIONS,false);'與'mapper.configure(MapperFeature.USE_WRAPPER_NAME_AS_PROPERTY_NAME,true)發生衝突;和'mapper.setVisibility(PropertyAccessor.FIELD,Visibility.NONE).setVisibility(PropertyAccessor.GETTER,Visibility.ANY);'。現在我想不出一個簡單的方法來解決這個問題,而不會搞亂Jackson的圖書館。另一種方法來解決你的用例看看我以前的帖子。 – nutlike 2013-03-08 09:08:52

+0

@ nutlike-謝謝。不,我沒有嘗試過mixin-annotations,但會給他們一個去。 – andthereitgoes 2013-03-08 15:30:17

回答

3

小例子,以示對你的使用情況與混入的解決方案:

class Data { 
    int totalUsers; 
    int totalBooks; 
} 

...

class DataMixin { 
    @JsonProperty("Total Users") 
    int totalUsers; 
    @JsonProperty("Total Books") 
    int totalBooks; 
} 

...

傑克遜2.0 - 2.4(在2.5棄用)

ObjectMapper mapper = new ObjectMapper(); 
if (pretty) { 
    mapper.addMixInAnnotations(Data.class, DataMixin.class); 
} 

傑克遜2.5+

ObjectMapper mapper = new ObjectMapper(); 
if (pretty) { 
    mapper.addMixin(Data.class, DataMixin.class); 
} 
+1

有趣的是,當我嘗試使用http://wiki.fasterxml.com/JacksonMixInAnnotations上給出的例子來設置它在模塊中並使用SetUpContext時。它不適合我。但我嘗試了一些類似於你發佈的例子,它的工作原理即不使用模塊,只是使用mapper.addMixInAnnotations – andthereitgoes 2013-03-08 17:42:05

+0

請記住,你必須註冊模塊爲傑克遜看到它,即使用'objectMapper.registerModule(new MyMixInModule( ));' – 2013-07-24 17:38:54