tujuan saya adalah untuk mengkonfigurasi objectMapper
sedemikian rupa sehingga hanya elemen yang diserialisasikan dengan yang dijelaskan @JsonProperty
.
Untuk melakukannya saya mengikuti penjelasan ini yang mengatakan bagaimana mengkonfigurasi objectmapper.
Saya menyertakan objectmapper kustom seperti yang dijelaskan di sini .
Namun ketika kelas NumbersOfNewEvents
tersebut dibuat berseri itu masih berisi semua atribut di json.
Apakah ada yang punya petunjuk? Terima kasih sebelumnya
Jackson 1.8.0 spring 3.0.5
CustomObjectMapper
public class CompanyObjectMapper extends ObjectMapper {
public CompanyObjectMapper() {
super();
setVisibilityChecker(getSerializationConfig()
.getDefaultVisibilityChecker()
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE)
.withFieldVisibility(JsonAutoDetect.Visibility.NONE)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.DEFAULT));
}
}
servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="de.Company.backend.web" />
<mvc:annotation-driven />
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</list>
</property>
</bean>
<bean id="jacksonObjectMapper" class="de.Company.backend.web.CompanyObjectMapper" />
</beans>
NumbersOfNewEvents
public class NumbersOfNewEvents implements StatusAttribute {
public Integer newAccepts;
public Integer openRequests;
public NumbersOfNewEvents() {
super();
}
}
JacksonConfiguration
? Ini adalah cara otomatis untuk menginstruksikan Spring Boot menggunakan kelas ini sebagai kelas konfigurasi untuk Jackson?@EnableWebMvc
? Saya ragu karena ... lihat jawaban saya : Mengapa penggunaan @EnableWebMvc menjadi masalah?Mungkin karena saya menggunakan Spring 3.1 (bukan Spring 3.0.5 sebagai pertanyaan Anda), tetapi jawaban Steve Eastwood tidak berhasil untuk saya. Solusi ini berfungsi untuk Spring 3.1:
Dalam konteks xml musim semi Anda:
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper" ref="jacksonObjectMapper" /> </bean> </mvc:message-converters> </mvc:annotation-driven> <bean id="jacksonObjectMapper" class="de.Company.backend.web.CompanyObjectMapper" />
sumber
Ada
org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean
untuk waktu yang lama. Mulai dari 1.2 rilis Spring Boot adaorg.springframework.http.converter.json.Jackson2ObjectMapperBuilder
untuk Java Config.Dalam konfigurasi String Boot bisa sesederhana:
spring.jackson.deserialization.<feature_name>=true|false spring.jackson.generator.<feature_name>=true|false spring.jackson.mapper.<feature_name>=true|false spring.jackson.parser.<feature_name>=true|false spring.jackson.serialization.<feature_name>=true|false spring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty
di
classpath:application.properties
atau beberapa kode Java di@Configuration
kelas:@Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd")); return builder; }
Lihat:
sumber
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json()
.Saya telah menggunakan ini dengan Jackson 2.x dan Spring 3.1.2+
servlet-context.xml:
Perhatikan bahwa elemen root adalah
<beans:beans>
, jadi Anda mungkin perlu menghapusbeans
dan menambahkanmvc
beberapa elemen ini tergantung pada pengaturan Anda.<annotation-driven> <message-converters> <beans:bean class="org.springframework.http.converter.StringHttpMessageConverter" /> <beans:bean class="org.springframework.http.converter.ResourceHttpMessageConverter" /> <beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <beans:property name="objectMapper" ref="jacksonObjectMapper" /> </beans:bean> </message-converters> </annotation-driven> <beans:bean id="jacksonObjectMapper" class="au.edu.unimelb.atcom.transfer.json.mappers.JSONMapper" />
au.edu.unimelb.atcom.transfer.json.mappers.JSONMapper.java:
public class JSONMapper extends ObjectMapper { public JSONMapper() { SimpleModule module = new SimpleModule("JSONModule", new Version(2, 0, 0, null, null, null)); module.addSerializer(Date.class, new DateSerializer()); module.addDeserializer(Date.class, new DateDeserializer()); // Add more here ... registerModule(module); } }
DateSerializer.java:
public class DateSerializer extends StdSerializer<Date> { public DateSerializer() { super(Date.class); } @Override public void serialize(Date date, JsonGenerator json, SerializerProvider provider) throws IOException, JsonGenerationException { // The client side will handle presentation, we just want it accurate DateFormat df = StdDateFormat.getBlueprintISO8601Format(); String out = df.format(date); json.writeString(out); } }
DateDeserializer.java:
public class DateDeserializer extends StdDeserializer<Date> { public DateDeserializer() { super(Date.class); } @Override public Date deserialize(JsonParser json, DeserializationContext context) throws IOException, JsonProcessingException { try { DateFormat df = StdDateFormat.getBlueprintISO8601Format(); return df.parse(json.getText()); } catch (ParseException e) { return null; } } }
sumber
Saya menemukan solusinya sekarang berdasarkan https://github.com/FasterXML/jackson-module-hibernate
Saya memperluas pemeta objek dan menambahkan atribut dalam konstruktor yang diwarisi.
Kemudian pemeta objek baru didaftarkan sebagai kacang.
<!-- https://github.com/FasterXML/jackson-module-hibernate --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <array> <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper"> <bean class="de.company.backend.spring.PtxObjectMapper"/> </property> </bean> </array> </property> </bean>
sumber
ObjectMapper
sebagai@Component
dan@Primary
. Ini adalah pendekatan yang direkomendasikan dalam Panduan Referensi Musim Semi dan telah bekerja dengan baik untuk saya.Jika Anda ingin menambahkan ObjectMapper kustom untuk mendaftarkan serializers kustom, coba jawaban saya.
Dalam kasus saya (Spring 3.2.4 dan Jackson 2.3.1), konfigurasi XML untuk serializer khusus:
<mvc:annotation-driven> <mvc:message-converters register-defaults="false"> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="serializers"> <array> <bean class="com.example.business.serializer.json.CustomObjectSerializer"/> </array> </property> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
dengan cara yang tidak dapat dijelaskan ditimpa kembali ke default oleh sesuatu.
Ini berhasil untuk saya:
CustomObject.java
@JsonSerialize(using = CustomObjectSerializer.class) public class CustomObject { private Long value; public Long getValue() { return value; } public void setValue(Long value) { this.value = value; } }
CustomObjectSerializer.java
public class CustomObjectSerializer extends JsonSerializer<CustomObject> { @Override public void serialize(CustomObject value, JsonGenerator jgen, SerializerProvider provider) throws IOException,JsonProcessingException { jgen.writeStartObject(); jgen.writeNumberField("y", value.getValue()); jgen.writeEndObject(); } @Override public Class<CustomObject> handledType() { return CustomObject.class; } }
Tidak ada konfigurasi XML (
<mvc:message-converters>(...)</mvc:message-converters>
) yang diperlukan dalam solusi saya.sumber
Saya menggunakan Spring 4.1.6 dan Jackson FasterXML 2.1.4.
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.fasterxml.jackson.databind.ObjectMapper"> <!-- 设置不输出null字段--> <property name="serializationInclusion" value="NON_NULL"/> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
ini berfungsi di konfigurasi applicationContext.xml saya
sumber
SOLUSI 1
Solusi kerja pertama (teruji) berguna terutama saat menggunakan @EnableWebMvc:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Autowired private ObjectMapper objectMapper;// created elsewhere @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // this won't add a 2nd MappingJackson2HttpMessageConverter // as the SOLUTION 2 is doing but also might seem complicated converters.stream().filter(c -> c instanceof MappingJackson2HttpMessageConverter).forEach(c -> { // check default included objectMapper._registeredModuleTypes, // e.g. Jdk8Module, JavaTimeModule when creating the ObjectMapper // without Jackson2ObjectMapperBuilder ((MappingJackson2HttpMessageConverter) c).setObjectMapper(this.objectMapper); }); }
SOLUSI 2
Tentu saja pendekatan umum di bawah ini juga berfungsi (juga bekerja dengan @EnableWebMvc):
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Autowired private ObjectMapper objectMapper;// created elsewhere @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { // this will add a 2nd MappingJackson2HttpMessageConverter // (additional to the default one) but will work and you // won't lose the default converters as you'll do when overwriting // configureMessageConverters(List<HttpMessageConverter<?>> converters) // // you still have to check default included // objectMapper._registeredModuleTypes, e.g. // Jdk8Module, JavaTimeModule when creating the ObjectMapper // without Jackson2ObjectMapperBuilder converters.add(new MappingJackson2HttpMessageConverter(this.objectMapper)); }
Mengapa penggunaan @EnableWebMvc menjadi masalah?
@EnableWebMvc menggunakan
DelegatingWebMvcConfiguration
extendsWebMvcConfigurationSupport
yang melakukan ini:if (jackson2Present) { Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json(); if (this.applicationContext != null) { builder.applicationContext(this.applicationContext); } messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); }
yang berarti bahwa tidak ada cara untuk memasukkan milik Anda sendiri
ObjectMapper
dengan tujuan mempersiapkannya untuk digunakan dalam membuat defaultMappingJackson2HttpMessageConverter
saat menggunakan @EnableWebMvc.sumber
Di Spring Boot
2.2.x
Anda perlu mengkonfigurasinya seperti ini:@Bean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { return builder.build() }
Kotlin:
@Bean fun objectMapper(builder: Jackson2ObjectMapperBuilder) = builder.build()
sumber
Di atas Spring 4, Anda tidak perlu melakukan konfigurasi
MappingJacksonHttpMessageConverter
jika Anda hanya bermaksud untuk mengkonfigurasiObjectMapper
.(konfigurasi
MappingJacksonHttpMessageConverter
akan menyebabkan Anda kehilangan MessageConverter lainnya)Anda hanya perlu melakukan:
public class MyObjectMapper extends ObjectMapper { private static final long serialVersionUID = 4219938065516862637L; public MyObjectMapper() { super(); enable(SerializationFeature.INDENT_OUTPUT); } }
Dan dalam konfigurasi Spring Anda, buat kacang ini:
@Bean public MyObjectMapper myObjectMapper() { return new MyObjectMapper(); }
sumber
_halObjectMapper: defined in null
Untuk mengonfigurasi konverter pesan di web pegas biasa, dalam hal ini untuk mengaktifkan Java 8 JSR-310 JavaTimeModule, Anda harus mengimplementasikannya
WebMvcConfigurer
di@Configuration
kelas terlebih dahulu lalu mengganticonfigureMessageConverters
metode:@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(new JavaTimeModule(), new Jdk8Module()).build() .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); converters.add(new MappingJackson2HttpMessageConverter(objectMapper)); }
Seperti ini, Anda dapat mendaftarkan kustom apa pun yang ditentukan
ObjectMapper
dalam konfigurasi Spring berbasis Java.sumber
extendMessageConverters
, sesuai dokumentasi Spring . Tetapi saya tidak membutuhkannya, karena saya hanya perlu yang disesuaikanMappingJackson2HttpMessageConverter
.Saya menggunakan Spring 3.2.4 dan Jackson FasterXML 2.1.1.
Saya telah membuat JacksonObjectMapper khusus yang berfungsi dengan anotasi eksplisit untuk setiap atribut Objek yang dipetakan:
package com.test; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; public class MyJaxbJacksonObjectMapper extends ObjectMapper { public MyJaxbJacksonObjectMapper() { this.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) .setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY) .setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE) .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE) .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE); this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); } }
Kemudian ini dibuat dalam konteks-konfigurasi ( servlet-konteks.xml ):
<mvc:annotation-driven> <mvc:message-converters> <beans:bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <beans:property name="objectMapper"> <beans:bean class="com.test.MyJaxbJacksonObjectMapper" /> </beans:property> </beans:bean> </mvc:message-converters> </mvc:annotation-driven>
Ini bekerja dengan baik!
sumber