<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          JSON序列化和反序列化還有這種玩法

          共 4349字,需瀏覽 9分鐘

           ·

          2021-11-26 21:39

          Mixin對(duì)于前端開發(fā)者可不陌生,Vue、React等知名前端框架都使用了Mixin。而對(duì)于后端開發(fā),尤其是Java后端開發(fā)來(lái)說Mixin卻是一個(gè)很陌生的概念。今天來(lái)我們通過Jackson讓后端開發(fā)者也來(lái)認(rèn)識(shí)一下Mixin。

          場(chǎng)景

          比如我們引用了一個(gè)Jar包,其中的某個(gè)類在某個(gè)場(chǎng)景需要反序列化,但是這個(gè)類沒有提供默認(rèn)構(gòu)造。咋辦呢?把原來(lái)的項(xiàng)目拉下來(lái),重寫一下?下下策! 你可以使用Jackson提供的Mixin特性來(lái)解決這個(gè)問題。

          Jackson中的Mixin

          Jackson中的?Mixin(混入)?我們可以這樣解讀它:將目標(biāo)對(duì)象無(wú)法實(shí)現(xiàn)的序列化或反序列化功能通過一個(gè)混入對(duì)象進(jìn)行配置,在序列化或反序列化的時(shí)候把這些個(gè)性化配置混入到目標(biāo)對(duì)象中?;烊氩桓淖兡繕?biāo)對(duì)象本身的任何特性,混入對(duì)象和目標(biāo)對(duì)象是映射的關(guān)系。接下來(lái)我們來(lái)實(shí)現(xiàn)一個(gè)混入的DEMO。

          Mixin的實(shí)現(xiàn)

          我們有一個(gè)User類,為了演示需要,我們極端一些,實(shí)際開發(fā)中不太會(huì)出現(xiàn)這種極端情況。這個(gè)User沒有無(wú)參構(gòu)造,也沒有屬性的getter方法。

          public?class?User?{
          ????private?final?String?name;
          ????private?final?Integer?age;

          ????public?User(String?name,?Integer?age)?{
          ????????this.name?=?name;
          ????????this.age?=?age;
          ????}
          ????@Override
          ????public?String?toString()?{
          ????????return?"User{"?+
          ????????????????"name='"?+?name?+?'\''?+
          ????????????????",?age="?+?age?+
          ????????????????'}';
          ????}
          }

          編寫Mixin類

          我想對(duì)這個(gè)極端的User進(jìn)行序列化和反序列化。按以前的玩法我們?cè)?code style="font-size: 14px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(53, 179, 120);background-color: rgba(27, 31, 35, 0.05);word-break: break-all;">User類上加上@JsonAutoDetect注解就可以實(shí)現(xiàn)序列化了;加上@JsonDeserialize注解并指定反序列化類就可以反序列化了。不過今天我們不需要對(duì)User進(jìn)行任何更改,只需要編寫一個(gè)Mixin類把上述兩個(gè)注解配置好就可以了。

          @JsonAutoDetect(fieldVisibility?=?JsonAutoDetect.Visibility.ANY,?getterVisibility?=?JsonAutoDetect.Visibility.NONE,
          ????????isGetterVisibility?=?JsonAutoDetect.Visibility.NONE)
          @JsonIgnoreProperties(ignoreUnknown?=?true)
          @JsonDeserialize(using?=?UserMixin.UserDeserializer.class)
          public?abstract?class?UserMixin?
          {

          ????/**
          ?????*?反序列化類
          ?????**/

          ????static?class?UserDeserializer?extends?JsonDeserializer<User>?{

          ????????@Override
          ????????public?User?deserialize(JsonParser?p,?DeserializationContext?ctxt)?throws?IOException?{
          ????????????ObjectMapper?mapper?=?(ObjectMapper)?p.getCodec();
          ????????????JsonNode?jsonNode?=?mapper.readTree(p);

          ????????????String?name?=?readJsonNode(jsonNode,?"name").asText(null);
          ????????????String?age?=?readJsonNode(jsonNode,?"age").asText(null);
          ????????????Integer?ageVal?=?Objects.isNull(age)??null:?Integer.valueOf(age);
          ????????????return?new?User(name,ageVal);
          ????????}

          ????????private?JsonNode?readJsonNode(JsonNode?jsonNode,?String?field)?{
          ????????????return?jsonNode.has(field)???jsonNode.get(field)?:?MissingNode.getInstance();
          ????????}
          ????}

          }

          ?

          其它注解可以參考往期的Jackson文章的介紹

          Mixin映射目標(biāo)類

          編寫完Mixin類后,我們通過ObjectMapper中的addMixIn方法把UserMixinUser映射起來(lái)。并編寫一個(gè)序列化和反序列化的例子。

          ????????ObjectMapper?objectMapper?=?new?ObjectMapper();
          ????????objectMapper.addMixIn(User.class,?UserMixin.class);

          ????????User?felord?=?new?User("felord",?12);
          ????????String?json?=?objectMapper.writeValueAsString(felord);
          ????????//{"name":"felord","age":12}?
          ????????System.out.println("json?=?"?+?json);

          ????????String?jsonStr?=?"{\"name\":\"felord\",\"age\":12}";

          ????????User?user?=?objectMapper.readValue(jsonStr,?User.class);
          ????????//?User{name='felord',?age=12}
          ????????System.out.println("user?=?"?+?user);

          這樣我們?cè)诓粚?duì)目標(biāo)類進(jìn)行任何改變的情況下實(shí)現(xiàn)了個(gè)性化的JSON序列化和反序列化。

          Jackson中的Module

          Jackson還提供了模塊化功能,可以將個(gè)性化配置進(jìn)行模塊化統(tǒng)一管理,而且可以按需引用,甚至可插拔。它同樣能夠管理一組Mixin。聲明一個(gè)Jackson Module非常簡(jiǎn)單,繼承SimpleModule覆寫它的一些方法即可。針對(duì)Mixin我們可以這樣寫:

          public?class?UserModule?extends?SimpleModule?{
          ???public?UserModule()?{
          ???????super(UserModule.class.getName());
          ???}

          ???@Override
          ???public?void?setupModule(SetupContext?context)?{
          ????????context.setMixInAnnotations(User.class,UserMixin.class);
          ???}
          }

          Module同樣可以注冊(cè)到ObjectMapper中,同樣也能實(shí)現(xiàn)我們想要的效果:

          ????????ObjectMapper?objectMapper?=?new?ObjectMapper();
          ????????objectMapper.registerModule(new?UserModule());
          ????????//?省略

          Module的功能更加強(qiáng)大。平常我們會(huì)使用以下幾個(gè)Module:

          • jackson-module-parameter-names?此模塊能夠訪問構(gòu)造函數(shù)和方法參數(shù)的名稱
          • jackson-datatype-jdk8?除了Java8的時(shí)間API外其它新特性的的支持
          • jackson-datatype-jsr310?用以支持Java8新增的JSR310時(shí)間API

          另外Spring Security也提供了Module支持SecurityJackson2Modules,它包含了下面的一些模塊:

          ??????ObjectMapper?mapper?=?new?ObjectMapper();
          ??????mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,?JsonTypeInfo.As.PROPERTY);
          ??????mapper.registerModule(new?CoreJackson2Module());
          ??????mapper.registerModule(new?CasJackson2Module());
          ??????mapper.registerModule(new?WebJackson2Module());
          ??????mapper.registerModule(new?WebServletJackson2Module());
          ??????mapper.registerModule(new?WebServerJackson2Module());
          ??????mapper.registerModule(new?OAuth2ClientJackson2Module());

          建議看一下SecurityJackson2Modules源碼,研究并模仿一下Module的使用。

          OAuth2.0中的scope和RBAC中的role有什么關(guān)系

          2021-11-16

          Spring OAuth2 授權(quán)服務(wù)器配置詳解

          2021-11-15

          授權(quán)服務(wù)器框架Spring Authorization Server的過濾器鏈

          2021-11-11

          Spring新的授權(quán)服務(wù)器Spring Authorization Server入門

          2021-11-09


          推薦關(guān)注本文作者:碼農(nóng)小胖哥

          分享高質(zhì)量編程知識(shí),探討IT人生

          技術(shù)干貨,實(shí)戰(zhàn)技巧,面試技巧,前沿資訊一個(gè)都不能少
          瀏覽 22
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品黄色电影 | 亚洲日韩欧美性爱 | 97超碰在 | 一级电影国产 | 黄色在线一区 |