Apakah ada cara menggunakan Prosesor Jackson JSON untuk melakukan serialisasi tingkat bidang khusus? Misalnya, saya ingin ada kelasnya
public class Person {
public String name;
public int age;
public int favoriteNumber;
}
diserialkan ke JSON berikut:
{ "name": "Joe", "age": 25, "favoriteNumber": "123" }
Perhatikan bahwa age = 25 dikodekan sebagai angka sementara favouriteNumber = 123 dikodekan sebagai string . Di luar kotak Jackson menyusun int
nomor. Dalam hal ini saya ingin favouriteNumber dikodekan sebagai string.
java
json
serialization
jackson
Steve Kuo
sumber
sumber
Jawaban:
Anda dapat menerapkan serializer khusus sebagai berikut:
public class Person { public String name; public int age; @JsonSerialize(using = IntToStringSerializer.class, as=String.class) public int favoriteNumber: } public class IntToStringSerializer extends JsonSerializer<Integer> { @Override public void serialize(Integer tmpInt, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { jsonGenerator.writeObject(tmpInt.toString()); } }
Java harus menangani autoboxing dari
int
menjadiInteger
untuk Anda.sumber
as=String.class
diabaikan karenausing
parameter, dan tidak diperlukan di sini. Catatan: jika using () juga digunakan, itu memiliki prioritas (karena ini secara langsung menentukan penyambung, sedangkan ini hanya akan digunakan untuk menemukan penyambung) dan nilai properti anotasi ini diabaikan.Person implements ToJson
?as=String.class
bagian, karena tipe yang saya gunakan. @ kevin-bowersox, saya sarankan untuk memperbarui komentar Anda, sejalan dengan apa yang dikatakan @GarethLatty.Jackson-databind (setidaknya 2.1.3) menyediakan khusus
ToStringSerializer
(com.fasterxml.jackson.databind.ser.std.ToStringSerializer
)Contoh:
public class Person { public String name; public int age; @JsonSerialize(using = ToStringSerializer.class) public int favoriteNumber: }
sumber
jackson-annotations menyediakan
@JsonFormat
yang dapat menangani banyak kustomisasi tanpa perlu menulis serializer kustom.Misalnya, meminta
STRING
bentuk untuk bidang dengan tipe numerik akan menghasilkan nilai numerik sebagai stringpublic class Person { public String name; public int age; @JsonFormat(shape = JsonFormat.Shape.STRING) public int favoriteNumber; }
akan menghasilkan keluaran yang diinginkan
{"name":"Joe","age":25,"favoriteNumber":"123"}
sumber
Tambahkan
@JsonProperty
pengambil beranotasi, yang mengembalikan aString
, untukfavoriteNumber
bidang:public class Person { public String name; public int age; private int favoriteNumber; public Person(String name, int age, int favoriteNumber) { this.name = name; this.age = age; this.favoriteNumber = favoriteNumber; } @JsonProperty public String getFavoriteNumber() { return String.valueOf(favoriteNumber); } public static void main(String... args) throws Exception { Person p = new Person("Joe", 25, 123); ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(p)); // {"name":"Joe","age":25,"favoriteNumber":"123"} } }
sumber
Jika Anda tidak ingin mencemari model Anda dengan anotasi dan ingin melakukan beberapa operasi kustom, Anda dapat menggunakan mixin.
ObjectMapper mapper = new ObjectMapper(); SimpleModule simpleModule = new SimpleModule(); simpleModule.setMixInAnnotation(Person.class, PersonMixin.class); mapper.registerModule(simpleModule);
Ganti usia:
public abstract class PersonMixin { @JsonSerialize(using = PersonAgeSerializer.class) public String age; }
Lakukan apapun yang Anda butuhkan dengan usia:
public class PersonAgeSerializer extends JsonSerializer<Integer> { @Override public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeString(String.valueOf(integer * 52) + " months"); } }
sumber
dengan bantuan @JsonView kita dapat memutuskan bidang kelas model untuk membuat serial yang memenuhi kriteria minimal (kita harus menentukan kriteria) seperti kita dapat memiliki satu kelas inti dengan 10 properti tetapi hanya 5 properti yang dapat dibuat bersambung yang diperlukan untuk klien hanya
Tentukan Tampilan kami hanya dengan membuat kelas berikut:
public class Views { static class Android{}; static class IOS{}; static class Web{}; }
Kelas model beranotasi dengan tampilan:
public class Demo { public Demo() { } @JsonView(Views.IOS.class) private String iosField; @JsonView(Views.Android.class) private String androidField; @JsonView(Views.Web.class) private String webField; // getters/setters ... .. }
Sekarang kita harus menulis konverter json khusus hanya dengan memperluas kelas HttpMessageConverter dari pegas sebagai:
public class CustomJacksonConverter implements HttpMessageConverter<Object> { public CustomJacksonConverter() { super(); //this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.ClientView.class)); this.delegate.getObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true); this.delegate.getObjectMapper().setSerializationInclusion(Include.NON_NULL); } // a real message converter that will respond to methods and do the actual work private MappingJackson2HttpMessageConverter delegate = new MappingJackson2HttpMessageConverter(); @Override public boolean canRead(Class<?> clazz, MediaType mediaType) { return delegate.canRead(clazz, mediaType); } @Override public boolean canWrite(Class<?> clazz, MediaType mediaType) { return delegate.canWrite(clazz, mediaType); } @Override public List<MediaType> getSupportedMediaTypes() { return delegate.getSupportedMediaTypes(); } @Override public Object read(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return delegate.read(clazz, inputMessage); } @Override public void write(Object obj, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { synchronized(this) { String userAgent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("userAgent"); if ( userAgent != null ) { switch (userAgent) { case "IOS" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.IOS.class)); break; case "Android" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.Android.class)); break; case "Web" : this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( Views.Web.class)); break; default: this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null )); break; } } else { // reset to default view this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null )); } delegate.write(obj, contentType, outputMessage); } } }
Sekarang ada kebutuhan untuk memberitahu spring untuk menggunakan custom json convert ini hanya dengan meletakkan ini di dispatcher-servlet.xml
<mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean id="jsonConverter" class="com.mactores.org.CustomJacksonConverter" > </bean> </mvc:message-converters> </mvc:annotation-driven>
Begitulah cara Anda dapat memutuskan bidang mana yang akan dibuat serial.
sumber