一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 如何利用Jackson序列化忽略指定類型的屬性詳解

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

2021-06-09 14:00隔葉黃鶯 Java教程

這篇文章主要給大家介紹了關于如何利用Jackson序列化忽略指定類型的屬性,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

前言

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

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

假設我們有一個 apache 的 schema 文件 user.avsc, 內容如下:

?
1
2
3
4
5
6
7
8
9
{
 "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 進行序列化時

?
1
2
3
objectmapper objectmapper = new objectmapper() ;
user user = user.newbuilder().setname("yanbin").setaddress("chicago").build();
system.out.println(objectmapper.writevalueasstring(user));

收到異常(關鍵信息)

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 對象的

?
1
public org.apache.avro.schema getschema() { return schema$; }

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

?
1
2
3
public schema getvaluetype() {
throw new avroruntimeexception("not a map: "+this);
}

因此,要實現序列化 apache avro 對象,解決的辦法有三

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

它們的實現分別如下

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

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

?
1
2
3
@jsonignoretype
@interface ignoreavroschemafield {
}

序列化 apache avro 對象前給 objectmapp 加一個 mixin

?
1
2
3
4
5
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 屬的輸出內容

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

定制化 schema 序列化方式

?
1
2
3
4
5
6
7
class avroschemaserializer extends jsonserializer<schema> {
 
 @override
 public void serialize(schema value, jsongenerator jgen, serializerprovider provider) throws ioexception {
 jgen.writestring(value.getfullname()); //直接輸出當前 apache avro 對象的全限類名
 }
}

給 objectmapper 加上定制的序列化器

?
1
2
3
4
5
6
7
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));

序列化后產生的輸出如下

{"name":"yanbin","address":"chicago","schema":"cc.unmi.data.user"}

如果在 avroschemaserializer 把 jgen.writestring(value.getfullname()) 替換如下

?
1
jgen.writestring(value.tostring());

并且序列化后對內容進行格式化輸出

?
1
2
3
4
5
6
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 外,filter 也像是干這事的,可以嘗試過下面的方式, 分兩步走

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

?
1
2
@jsonfilter("filter out apache avro schema field") //字符串值要與下面 addfilter("xxx") 保持一致
class propertyfiltermixin {}

給 objectmapper 設置 filter

?
1
2
3
4
5
6
7
8
objectmapper objectmapper = new objectmapper() ;
objectmapper.addmixin(specificrecordbase.class, propertyfiltermixin.class); //對 specificrecordbase 類型的對象應用
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"}

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

鏈接:

總結

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

原文鏈接:https://yanbin.blog/jackson-ignore-specified-field-type/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产白白视频在线观看2 | 大妹子最新视频在线观看 | 成人福利在线播放 | 日本中文字幕在线精品 | 99热久久国产精品这里 | 男人亚洲天堂 | 五月色天在线视频综合观看 | 九九热在线免费观看 | 91久久精品青青草原伊人 | 青青热久免费精品视频网站 | 精品亚洲永久免费精品 | 91极品女神久色在线播放 | 狠狠干快播 | 国产短视频精品一区二区三区 | 亚洲国产天堂综合一区 | 爽新片xxxxxxx| 娇妻被老外疯狂调教 | 免费观看毛片视频 | 日本免费不卡在线一区二区三区 | 吃大胸寡妇的奶 | 456成人免费高清视频 | 国产人成77777视频网站 | 91制片厂制作果冻传媒123 | 国产成人盗拍精品免费视频 | 校花被强迫np肉高h 校服下的白嫩小乳尖h1v1 | 色图片小说 | 免费又爽又黄禁片视频在线播放 | 日本欧美强乱视频在线 | 色哟哟哟在线精品观看视频 | 国产在线观看精品香蕉v区 国产在线观看a | 暖暖 免费 高清 日本 在线1 | 91麻豆国产精品91久久久 | 四虎国产精品免费久久麻豆 | 69re在线观看 | 公交车强校花系列小说 | 久久aa毛片免费播放嗯啊 | 国产成人理在线观看视频 | juliaann丝袜精品系列 | 91制片厂制作果冻传媒八夷 | 国产精品二区高清在线 | 四虎影视国产精品婷婷 |