欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何利用Jackson序列化忽略指定類型的屬性詳解

 更新時間:2018年11月01日 11:07:15   作者:隔葉黃鶯  
這篇文章主要給大家介紹了關(guān)于如何利用Jackson序列化忽略指定類型的屬性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

本文準確來講是探討如何用 Jackson 來序列化 Apache avro 對象,因為簡單用 Jackson 來序列化 Apache avro 對象會報錯。原因是序列化 Schema getSchema() 時會報錯,后面會講到,需要序列化時忽略該屬性。那么能不能在 getSchema() 上加上 @JsonIgnore 來忽略該屬性呢?原理上是通的。不過手工修改的 avsc 生成的 Java 文件隨時會因為重新編譯而還原,所以不太具有實際可操作性,當然通過定制編譯 avsc 用的模板文件來加入 @JsonIgnore 是另一回事。

由于不能在要忽略的字段上添加 JsonIgnore 來控制,而如果我們明確了要忽略的字段類型的話,是能夠定制 Jackson 的  ObjectMapper  來屏蔽某個特定的類型。來看下面序列化 Apache avro 對象的例子:

假設(shè)我們有一個 Apache 的 Schema 文件 user.avsc, 內(nèi)容如下:

{
 "namespace": "cc.unmi.data",
 "type": "record",
 "name": "User",
 "fields": [
 {"name": "name", "type": "string"},
 {"name": "address", "type": ["string", "null"]}
 ]
}

編譯用 avro-tools compile schema user.avsc . 生成 cc.unmi.data.User.java 源文件,當我們試圖對類型的對象用 Jackson 進行序列化時

ObjectMapper objectMapper = new ObjectMapper() ;
User user = User.newBuilder().setName("Yanbin").setAddress("Chicago").build();
System.out.println(objectMapper.writeValueAsString(user));

收到異常(關(guān)鍵信息)

Caused by: org.apache.avro.AvroRuntimeException: Not a map: {"type":"record","name":"User","namespace":"cc.unmi.data","fields":[{"name":"name","type":"string"},{"name":"address","type":["string","null"]}]}
    at org.apache.avro.Schema.getValueType(Schema.java:294)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:664)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:689)

從上面的錯誤可以定位到 Jackson 的試圖序列化 User 對象的

 public org.apache.avro.Schema getSchema() { return SCHEMA$; }

而 org.apache.avro.Schema 中的 getValueType() 直接拋出異常拒絕被歸化

 public Schema getValueType() {
 throw new AvroRuntimeException("Not a map: "+this);
 }

因此,要實現(xiàn)序列化 Apache avro 對象,解決的辦法有三

  • 凡是 org.apache.avro.Schema 的屬性不被序列化(Schema 輸出確實用處不大)
  • 或?qū)τ趏rg.apache.avro.Schema 類型的屬性定制序列化,比如輸出為完整類名,或 Schema 定義的文本內(nèi)容
  • 再來一個,對 SpecificRecordBase 類型的 schema 名稱的屬性進行忽略(avro 類型繼承自 SpecificRecordBase)

它們的實現(xiàn)分別如下

忽略序列化指定類型的屬性

先定義一個標注了 @JsonIgnoreType 的注解

@JsonIgnoreType
@interface IgnoreAvroSchemaField {
}

序列化 Apache avro 對象前給 ObjectMapp 加一個 mixin

ObjectMapper objectMapper = new ObjectMapper() ;
objectMapper.addMixIn(Schema.class, IgnoreAvroSchemaField.class);
 
User user = User.newBuilder().setName("Yanbin").setAddress("Chicago").build();
System.out.println(objectMapper.writeValueAsString(user));

有了上面高度行的代碼,這兒的 Apache avro User 對象就能被正常序列化了,輸出為

{"name":"Yanbin","address":"Chicago"}

這樣 getSchema() 返回的類型,或另何對象中有 org.apache.avro.Schema 類型的屬性都會在序列化時忽略掉

定制 Schema 屬的輸出內(nèi)容

對于 Schema 類型的屬性,除了前面采取堵的方式,還可以因利疏導,即定制 Schema 屬性值的輸出內(nèi)容

定制化 Schema 序列化方式

class AvroSchemaSerializer extends JsonSerializer<Schema> {
 
 @Override
 public void serialize(Schema value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
 jgen.writeString(value.getFullName()); //直接輸出當前 Apache avro 對象的全限類名
 }
}

給 ObjectMapper 加上定制的序列化器

ObjectMapper objectMapper = new ObjectMapper() ;
SimpleModule simpleModule = new SimpleModule("SimpleModule", Version.unknownVersion());
simpleModule.addSerializer(Schema.class, new AvroSchemaSerializer());
objectMapper.registerModule(simpleModule);
 
User user = User.newBuilder().setName("Yanbin").setAddress("Chicago").build();
System.out.println(objectMapper.writeValueAsString(user));

序列化后產(chǎn)生的輸出如下

{"name":"Yanbin","address":"Chicago","schema":"cc.unmi.data.User"}

如果在 AvroSchemaSerializer 把 jgen.writeString(value.getFullName()) 替換如下

 jgen.writeString(value.toString());

并且序列化后對內(nèi)容進行格式化輸出

 System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));
{
 "name" : "Yanbin",
 "address" : "Chicago",
 "schema" : "{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"cc.unmi.data\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"address\",\"type\":[\"string\",\"null\"]}]}"
}

指定特定對象的屬性名進行過濾

從語義上除了 Ignore 外,F(xiàn)ilter 也像是干這事的,可以嘗試過下面的方式, 分兩步走

定義一個帶 @JsonFilter 的注解,也是不顯示注解到任何類

@JsonFilter("filter out apache avro schema field") //字符串值要與下面 addFilter("xxx") 保持一致
class PropertyFilterMixIn {}

給 ObjectMapper 設(shè)置 filter

 ObjectMapper objectMapper = new ObjectMapper() ;
 objectMapper.addMixIn(SpecificRecordBase.class, PropertyFilterMixIn.class); //對 SpecificRecordBase 類型的對象應(yīng)用
 FilterProvider filterProvider = new SimpleFilterProvider() //對 SpecificRecordBase 類型(如 User) 的名為 "schema" 屬性屏蔽
  .addFilter("filter out apache avro schema field", SimpleBeanPropertyFilter.serializeAllExcept("schema"));
 objectMapper.setFilterProvider(filterProvider);
 
 User user = User.newBuilder().setName("Yanbin").setAddress("Chicago").build();
 System.out.println(objectMapper.writeValueAsString(user));

輸出效果沒有意外,也能避免序列化 schema 屬性

{"name":"Yanbin","address":"Chicago"}

這最后一種方式是本篇寫作行將結(jié)束時找到并驗證的,所以不寫出來,不進行梳理可能永遠只會第一種方法。

鏈接:

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Java中List排序的三種實現(xiàn)方法實例

    Java中List排序的三種實現(xiàn)方法實例

    其實Java針對數(shù)組和List的排序都有實現(xiàn),對數(shù)組而言你可以直接使用Arrays.sort,對于List和Vector而言,你可以使用Collections.sort方法,下面這篇文章主要給大家介紹了關(guān)于Java中List排序的三種實現(xiàn)方法,需要的朋友可以參考下
    2021-12-12
  • SpringApplicationRunListener監(jiān)聽器源碼詳解

    SpringApplicationRunListener監(jiān)聽器源碼詳解

    這篇文章主要介紹了SpringApplicationRunListener監(jiān)聽器源碼詳解,springboot提供了兩個類SpringApplicationRunListeners、SpringApplicationRunListener(EventPublishingRunListener),spring框架還提供了一個ApplicationListener接口,需要的朋友可以參考下
    2023-11-11
  • java實現(xiàn)文本框和文本區(qū)的輸入輸出

    java實現(xiàn)文本框和文本區(qū)的輸入輸出

    這篇文章主要介紹了java實現(xiàn)文本框和文本區(qū)的輸入輸出的方法和具體示例,有需要的小伙伴可以參考下。
    2015-06-06
  • java項目中的絕對路徑和相對路徑用法說明

    java項目中的絕對路徑和相對路徑用法說明

    這篇文章主要介紹了java項目中的絕對路徑和相對路徑用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 一文詳解Java線程中的安全策略

    一文詳解Java線程中的安全策略

    Java中的線程到底有哪些安全策略呢?這篇文章將詳細為大家分析一下。文中的示例代碼講解詳細,對我們學習或工作有一定幫助,需要的可以參考一下
    2022-05-05
  • SpringBoot2整合Drools規(guī)則引擎及案例詳解

    SpringBoot2整合Drools規(guī)則引擎及案例詳解

    這篇文章主要介紹了SpringBoot2整合Drools規(guī)則引擎及案例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • MyBatis Generator配置入門

    MyBatis Generator配置入門

    本文主要介紹了MyBatis Generator配置入門,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • java 線程池封裝及拒絕策略示例詳解

    java 線程池封裝及拒絕策略示例詳解

    這篇文章主要為大家介紹了java 線程池封裝及拒絕策略示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • 關(guān)于spring的自定義緩存注解分析

    關(guān)于spring的自定義緩存注解分析

    這篇文章主要介紹了關(guān)于spring的自定義緩存注解分析,因為所有的key的失效時間都一樣,要想實現(xiàn)不同的key不同的失效時間,就得需要自定義緩存注解,需要的朋友可以參考下
    2023-05-05
  • 深入理解Java編程線程池的實現(xiàn)原理

    深入理解Java編程線程池的實現(xiàn)原理

    這篇文章主要介紹了深入理解Java編程線程池的實現(xiàn)原理,涉及ThreadPoolExecutor類,線程池實現(xiàn)原理及示例等相關(guān)內(nèi)容,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11

最新評論