最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java如何用一個統(tǒng)一結(jié)構(gòu)接收成員名稱不固定的數(shù)據(jù)

 更新時間:2024年11月29日 16:09:30   作者:mzlogin  
這篇文章主要為大家詳細介紹了Java如何用一個統(tǒng)一結(jié)構(gòu)接收成員名稱不固定的數(shù)據(jù),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

本文介紹了一種 Java 中如何用一個統(tǒng)一結(jié)構(gòu)接收成員名稱不固定的數(shù)據(jù)的方法。

背景

最近在做企業(yè)微信的內(nèi)部應(yīng)用開發(fā),遇到了一個小問題:企業(yè)微信的不同接口,返回的數(shù)據(jù)的結(jié)構(gòu)不完全一樣。

比如,獲取部門列表接口返回的數(shù)據(jù)結(jié)構(gòu)是這樣的:

{
    "errcode": 0,
    "errmsg": "ok",
    "department": [
        {
            "id": 2,
            "name": "廣州研發(fā)中心",
            "name_en": "RDGZ",
            "department_leader":["zhangsan","lisi"],
            "parentid": 1,
            "order": 10
        }
    ]
}

而獲取部門成員接口返回的數(shù)據(jù)結(jié)構(gòu)是這樣的:

{
    "errcode": 0,
    "errmsg": "ok",
    "userlist": [
        {
            "userid": "zhangsan",
            "name": "張三",
            "department": [1, 2],
            "open_userid": "xxxxxx"
        }
    ]
}

就是說,不同接口的返回框架是一樣的,都是 errcode + errmsg + 數(shù)據(jù)部分,但數(shù)據(jù)部分的成員名稱不一樣,比如上面的 department 和 userlist。

我不知道為什么這樣設(shè)計,從 Java 開發(fā)者的習(xí)慣來講,如果由我來設(shè)計,我會盡量保持接口返回的數(shù)據(jù)結(jié)構(gòu)的一致性,比如數(shù)據(jù)部分都用 data 來表示,這樣在序列化、反序列化的時候可以用一個統(tǒng)一的泛型結(jié)構(gòu)來進行。

當然這可能是企微內(nèi)部的開發(fā)語言或習(xí)慣的差異,或者其它原因,這里也無法深究,只談如何應(yīng)對。

分析

遇到這個問題后,第一反應(yīng)是用 JSON 結(jié)構(gòu)來接收,然后不同接口的數(shù)據(jù)部分用不同的 key 來讀取??梢詫崿F(xiàn),但總覺得不夠優(yōu)雅。

然后想到 GitHub 上應(yīng)該有不少開源的企微開發(fā)的封裝庫,去看看它們的實現(xiàn),說不定會有更好的方案,最終果然有收獲。

主要看了兩個庫:

前者 WxJava 知名度更高,包含的東西也更多,包含微信、企微的各種開發(fā)包的封裝。它這塊的實現(xiàn)是用我們前面提到的方法,用 JSON 結(jié)構(gòu)來接收,然后不同接口的數(shù)據(jù)用不同的 key 來讀取。

后者 wecom-sdk 是企微的開發(fā)包。它這塊的實現(xiàn)是用了一個統(tǒng)一的泛型結(jié)構(gòu)來接收數(shù)據(jù)。

以下分別截取兩個庫的兩個部門管理相關(guān)接口的封裝代碼:

WxJava 版:

github.com/binarywang/WxJava/blob/develop/weixin-java-cp/src/main/java/me/chanjar/weixin/cp/api/impl/WxCpDepartmentServiceImpl.java

@Override
public List<WxCpDepart> list(Long id) throws WxErrorException {
    String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_LIST);
    if (id != null) {
      url += "?id=" + id;
    }

    String responseContent = this.mainService.get(url, null);
    JsonObject tmpJsonObject = GsonParser.parse(responseContent);
    return WxCpGsonBuilder.create()
      .fromJson(tmpJsonObject.get("department"),
        new TypeToken<List<WxCpDepart>>() {
        }.getType()
      );
  }

@Override
public List<WxCpDepart> simpleList(Long id) throws WxErrorException {
    String url = this.mainService.getWxCpConfigStorage().getApiUrl(DEPARTMENT_SIMPLE_LIST);
    if (id != null) {
      url += "?id=" + id;
    }

    String responseContent = this.mainService.get(url, null);
    JsonObject tmpJsonObject = GsonParser.parse(responseContent);
    return WxCpGsonBuilder.create()
      .fromJson(tmpJsonObject.get("department_id"),
        new TypeToken<List<WxCpDepart>>() {
        }.getType()
      );
  }
}

wecom-sdk 版:

github.com/NotFound403/wecom-sdk/blob/release/wecom-sdk/src/main/java/cn/felord/api/DepartmentApi.java

@GET("department/list")
GenericResponse<List<DeptInfo>> deptList(@Query("id") long departmentId) throws WeComException;

@GET("department/simplelist")
GenericResponse<List<DeptSimpleInfo>> getSimpleList(@Query("id") long departmentId) throws WeComException;

拋開 wecom-sdk 版引入了 Retrofit2 庫的支持導(dǎo)致的代碼量銳減,在返回數(shù)據(jù)的反序列化上,我也更傾向于 wecom-sdk 版的實現(xiàn)。

實現(xiàn)

那接下來我們直接參照 wecom-sdk 里的實現(xiàn)方式,寫一個泛型類,就可以用來接收企微的不同接口返回的數(shù)據(jù)了:

@Data
public class WxWorkResponse<T> {

    @JsonProperty("errmsg")
    private String errMsg;

    @JsonProperty("errcode")
    private Integer errCode;

    @JsonAlias({
            "department",
            "userlist"
    })
    private T data;
}

這里面起到關(guān)鍵作用的是 Jackson 庫里的 @JsonAlias 注解。它的官方文檔是這樣介紹的:

Annotation that can be used to define one or more alternative names for a property, accepted during deserialization as alternative to the official name. Alias information is also exposed during POJO introspection, but has no effect during serialization where primary name is always used.
Examples:
  public class Info {
    @JsonAlias({ "n", "Name" })
    public String name;
  }
  
NOTE: Order of alias declaration has no effect. All properties are assigned in the order they come from incoming JSON document. If same property is assigned more than once with different value, later will remain. For example, deserializing
   public class Person {
      @JsonAlias({ "name", "fullName" })
      public String name;
   }
   
from
   { "fullName": "Faster Jackson", "name": "Jackson" }
   
will have value "Jackson".
Also, can be used with enums where incoming JSON properties may not match the defined enum values. For instance, if you have an enum called Size with values SMALL, MEDIUM, and LARGE, you can use this annotation to define alternate values for each enum value. This way, the deserialization process can map the incoming JSON values to the correct enum values.
Sample implementation:
public enum Size {
       @JsonAlias({ "small", "s", "S" })
       SMALL,
  
       @JsonAlias({ "medium", "m", "M" })
       MEDIUM,
  
       @JsonAlias({ "large", "l", "L" })
       LARGE
   }
During deserialization, any of these JSON structures will be valid and correctly mapped to the MEDIUM enum value: {"size": "m"}, {"size": "medium"}, or {"size": "M"}.

回到我們的例子,除了 department 和 userlist 之外還用到其它的 key,可以繼續(xù)在 @JsonAlias 注解里添加。

這樣,對不同的接口的封裝,我們反序列化后統(tǒng)一 getData() 就可以獲取到數(shù)據(jù)部分了,使用時不用再去操心數(shù)據(jù)部分的 key 是什么。

以上就是Java如何用一個統(tǒng)一結(jié)構(gòu)接收成員名稱不固定的數(shù)據(jù)的詳細內(nèi)容,更多關(guān)于Java統(tǒng)一結(jié)構(gòu)接收不固定數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實現(xiàn)后臺數(shù)據(jù)顯示在前端

    java實現(xiàn)后臺數(shù)據(jù)顯示在前端

    這篇文章主要為大家詳細介紹了java實現(xiàn)后臺數(shù)據(jù)顯示在前端,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 一文帶你深入了解Java8 Stream流式編程

    一文帶你深入了解Java8 Stream流式編程

    在實際項目當中,若能熟練使用Java8 的Stream流特性進行開發(fā),就比較容易寫出簡潔優(yōu)雅的代碼。本文主要就是基于實際項目常用的Stream Api流式處理總結(jié),希望對大家有所幫助
    2023-04-04
  • Java中API的使用方法詳情

    Java中API的使用方法詳情

    這篇文章主要介紹了Java中API的使用方法詳情,指的就是?JDK?中提供的各種功能的?Java類,這些類將底層的實現(xiàn)封裝了起來,我們不需要關(guān)心這些類是如何實現(xiàn)的,只需要學(xué)習(xí)這些類如何使用即可,我們可以通過幫助文檔來學(xué)習(xí)這些API如何使用,需要的朋友可以參考下
    2022-04-04
  • Spring中@Async用法詳解及簡單實例

    Spring中@Async用法詳解及簡單實例

    這篇文章主要介紹了Spring中@Async用法詳解及簡單實例的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Spring中事務(wù)管理的四種方法(銀行轉(zhuǎn)賬為例)

    Spring中事務(wù)管理的四種方法(銀行轉(zhuǎn)賬為例)

    這篇文章主要給大家介紹了關(guān)于Spring中事務(wù)管理的四種方法,文中是以銀行轉(zhuǎn)賬為例,通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • 詳解Java如何給按鈕添加監(jiān)視器

    詳解Java如何給按鈕添加監(jiān)視器

    這篇文章主要介紹了詳解Java如何給按鈕添加監(jiān)視器,使用匿名對象、實現(xiàn)接口、實現(xiàn)類、Lambda表達式、注解等,需要的朋友可以參考下
    2023-04-04
  • Java中do-while循環(huán)的使用方法及注意事項詳解

    Java中do-while循環(huán)的使用方法及注意事項詳解

    這篇文章主要介紹了Java中do-while循環(huán)的使用方法及注意事項的相關(guān)資料,在Java編程中,do-while循環(huán)是一種基本的循環(huán)控制結(jié)構(gòu),它至少執(zhí)行一次循環(huán)體,然后根據(jù)條件判斷是否繼續(xù),文中將用法介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • Java讀取properties文件內(nèi)容的幾種方式詳解

    Java讀取properties文件內(nèi)容的幾種方式詳解

    這篇文章主要介紹了Java讀取properties文件內(nèi)容的幾種方式詳解,讀取properties配置文件在實際的開發(fā)中使用的很多,本文來介紹常用的幾種實現(xiàn)方式,需要的朋友可以參考下
    2023-11-11
  • 實例講解Java 自旋鎖

    實例講解Java 自旋鎖

    這篇文章主要介紹了Java 自旋鎖的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java并發(fā),感興趣的朋友可以了解下
    2020-09-09
  • 通過mybatis-plus進行數(shù)據(jù)庫字段加解密方式

    通過mybatis-plus進行數(shù)據(jù)庫字段加解密方式

    文章主要介紹了在Java開發(fā)中,從編寫處理程序(handler)到實現(xiàn)加解密工具(util),再到配置實體和字段,以及自定義MyBatis的mapper語句的全過程
    2026-01-01

最新評論

甘谷县| 昆山市| 孝昌县| 花垣县| 合江县| 秭归县| 海丰县| 凤翔县| 罗江县| 安多县| 竹山县| 齐河县| 苍溪县| 衡南县| 上杭县| 格尔木市| 全椒县| 延庆县| 梅州市| 临城县| 调兵山市| 宝兴县| 岢岚县| 德庆县| 庆城县| 沁源县| 安阳县| 涞水县| 铅山县| 开江县| 府谷县| 商南县| 扬中市| 昌邑市| 杨浦区| 甘孜县| 郸城县| 星座| 晴隆县| 六枝特区| 张掖市|