javascript
使用@JsonIdentityInfo的Spring自定义序列化器
介紹
Spring中從JSON到JSON的序列化/反序列化已廣泛用于基于Spring的現(xiàn)代應(yīng)用程序中。 它基于杰克遜。 Jackson可以輕松地將任何POJO序列化為JSON,反之亦然。 這段代碼寫得很好。 我從未遇到任何問題。 當(dāng)涉及到自定義序列化程序時,它將變得更加困難。 這篇文章展示了如何在帶有自動裝配字段的Spring中使用自定義序列化程序。
定義自定義序列化器
通常,自定義類的自定義序列化器繼承自
com.fasterxml.jackson.databind.ser.std.StdSerializer。 此類定義了一些構(gòu)造函數(shù),但是框架只需要一個無參數(shù)的構(gòu)造函數(shù)即可調(diào)用超類,如下所示:
然后是實際編寫JSON必須實現(xiàn)的主要方法:
@Override public void serialize(ObjectToSerialize value, JsonGenerator gen, SerializerProvider provider) throws IOException {gen.writeStartObject();...provider.defaultSerializeField("some field", value.getField(), gen);...gen.writeEndObject(); }創(chuàng)建序列化程序類時,必須將其注冊為ObjectToSerialize的序列化程序。 這可以通過在類上使用@JsonSerialize注釋來完成:
@JsonSerialize(using = CustomSerializer.class) public class ObjectToSerialize { 現(xiàn)在,杰克遜將對該類的所有實例使用此自定義序列化程序。 如有必要,可以通過子類編寫自定義解串器
com.fasterxml.jackson.databind.deser.std.StdDeserializer <T>
循環(huán)引用和@JsonIdentityInfo
對于大多數(shù)使用Spring和Hibernate的商業(yè)應(yīng)用,遲早會出現(xiàn)循環(huán)引用的問題。 這是一個簡單的例子。
我們有2個課程:
public class Building {@Id@GeneratedValue(<parameters>)private Long id;private Set<Apartment> apartments; }public class Apartment {@Id@GeneratedValue(<parameters>)private Long id;private Building building; }如果我們嘗試序列化至少有一個公寓的建筑物,則會收到StackOverflowException。
杰克遜有一個解決此問題的方法-@JsonIdentityInfo。
如果將注釋@JsonIdentityInfo添加到此類,則:
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") public class ObjectToSerialize {那么任何ObjectMapper都將通過用其ID替換除第一個對象以外的所有對象的出現(xiàn)而打破循環(huán)。 像這樣:
{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}] }這些是Jackson提供的用于自定義序列化和處理循環(huán)引用的工具。
JSON結(jié)構(gòu)問題
問題
@JsonIdentityInfo適用于簡單的應(yīng)用程序。 但是隨著應(yīng)用程序以默認(rèn)格式增長,它可能會影響JSON的結(jié)構(gòu)。 例如,如果某些方法在一個響應(yīng)中返回建筑物和區(qū)域,則可能會發(fā)生以下情況:
{"buildings": [{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}]}],"districts": [{"buildings": [{"id": 5,...},1, - the object is replaced with its ID{"id": 6,...}]}] }從解析器的角度來看,這種替換可能非常不可預(yù)測。 在數(shù)組中,它可能會遇到對象和ID。 這可能發(fā)生在任何字段和任何對象上。 如果序列化提供程序多次發(fā)現(xiàn)該對象,則使用@JsonIdentityInfo對該類進行注釋的任何對象都將替換為其ID。 序列化提供程序找到的具有相同ID的每個第二,第三,第四等實例都將替換為其ID。
解
這里的解決方案是使用單獨的ObjectMapper編寫JSON的一部分。 已經(jīng)看到的ID的列表存儲在由ObjectMapper創(chuàng)建的序列化提供程序中。 通過創(chuàng)建單獨的ObjectMapper(具有可能不同的配置),可以重置列表。
對于返回不同對象類型的“復(fù)合” JSON結(jié)果,可以編寫自定義序列化程序。 在此自定義序列化程序中,“標(biāo)頭”是使用JsonGenerator方法手動編寫的,當(dāng)達到JSON中的正確級別時,我們將創(chuàng)建一個新的ObjectMapper并編寫外觀更好的JSON。
{"buildings": [ - create a new ObjectMapper{"id": 1,"apartments": [{"id": 2,"building": 1 - the object is replaced with its ID},{"id": 3,"building": 1 - the object is replaced with its ID}]}],"districts": [ - create a new ObjectMapper{"buildings": [{"id": 5,...},{ - the object is written as a JSON Object not an ID"id": 1,...},{"id": 6,...}]}] } 要將JSON寫入原始生成器,我們可以使用
ObjectMapper.writeValueAsString和
JsonGenerator.writeRawValue(String)。
PS也可以通過以下方式創(chuàng)建新的序列化提供程序
DefaultSerializerProvider.createInstance(SerializationConfig,SerializerFactory),但它可能更復(fù)雜。
自定義序列化器自動裝配問題
問題
我們希望能夠在自定義序列化程序中使用@Autowire。 這是Spring的最佳功能之一! 實際上,如果使用默認(rèn)的ObjectMapper,它就可以工作。 但是,如果我們使用JSON結(jié)構(gòu)問題的解決方案,則該解決方案不適用于由我們自己的對象映射器實例化的自定義序列化程序。
解
我們自己的對象映射器必須配置有特殊的HandlerInstantiator:
// try to use the default configuration as much as possible ObjectMapper om = Jackson2ObjectMapperBuilder.json().build(); // This instantiator will handle autowiring properties into the custom serializers om.setHandlerInstantiator( new SpringHandlerInstantiator(this.applicationContext.getAutowireCapableBeanFactory()));如果自定義對象映射器是在另一個由默認(rèn)ObjectMapper創(chuàng)建的自定義序列化器中創(chuàng)建的,則它可以自動裝配ApplicationContext。
翻譯自: https://www.javacodegeeks.com/2019/01/spring-custom-serializers-jsonidentityinfo.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的使用@JsonIdentityInfo的Spring自定义序列化器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 无法自己的意思 词语无法自已的意思
- 下一篇: spring jms 事务_Spring