Java 自定义对象映射器

Java 自定义对象映射器,java,json,jackson,Java,Json,Jackson,我有一个用例,其中我需要维护两组JSON输出,一组具有JSON属性的漂亮名称,另一组没有。因此,我决定自定义ObjectMapper,以便它忽略字段上的@JsonProperty(“pretty name”)注释,并使用字段属性名称。在本例中,您希望获得以下JSON输出 {"result":{"data":[{"totalUsers":12345,"totalBooks":883}]}} 具有漂亮名称的JSON输出如下所示 {"result":{"data":[{"Total Users":1

我有一个用例,其中我需要维护两组JSON输出,一组具有JSON属性的漂亮名称,另一组没有。因此,我决定自定义ObjectMapper,以便它忽略字段上的@JsonProperty(“pretty name”)注释,并使用字段属性名称。在本例中,您希望获得以下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。请参阅下面的stacktrace

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)
问题出在at中的这行代码中

com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._renameWithWrappers(POJOPropertiesCollector.java:728) 
其中_annotationIntrosector为空

PropertyName wrapperName = _annotationIntrospector.findWrapperName(member);

我不太清楚我该怎么做才能实现我的目标。有什么建议吗?谢谢。

小示例展示了针对您的混入用例的解决方案:

class Data {
    int totalUsers;
    int totalBooks;
}

Jackson 2.0-2.4(在2.5中不推荐使用)

Jackson 2.5+

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

只是一个想法:你是否考虑过使用混合打印注释来代替漂亮的打印JSON?(也许我明天会抽出时间来研究您的实际问题。)我做了一个简短的测试,显然
mapper.configure(MapperFeature.USE_ANNOTATIONS,false)与映射器.configure冲突(MapperFeature.USE\u WRAPPER\u NAME\u AS\u PROPERTY\u NAME,true)
mapper.setVisibility(PropertyAccessor.FIELD,Visibility.NONE)、setVisibility(PropertyAccessor.GETTER,Visibility.ANY)。现在,我想不出一个简单的方法来解决这个问题,而不干扰杰克逊的图书馆。有关解决用例的另一种方法,请参阅我之前的帖子。@nutlike-谢谢。不,我没有尝试过mixin注释,但会尝试一下。添加了一个小示例作为答案,我希望它能帮助您入门。有趣的是,当我尝试使用上给出的示例时,即在模块中设置它并使用SetUpContext。这对我不起作用。但我尝试了一些类似于您发布的示例的方法,它起了作用,即不使用模块,只使用mapper.addMixinNotations请记住,您必须为Jackson注册模块才能看到它,即使用
objectMapper.registerModule(新的MyMixInModule())
ObjectMapper mapper = new ObjectMapper();
if (pretty) {
    mapper.addMixInAnnotations(Data.class, DataMixin.class);
}
ObjectMapper mapper = new ObjectMapper();
if (pretty) {
    mapper.addMixin(Data.class, DataMixin.class);
}