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

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

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

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

背景

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

比如,獲取部門(mén)列表接口返回的數(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
        }
    ]
}

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

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

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

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

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

分析

遇到這個(gè)問(wèn)題后,第一反應(yīng)是用 JSON 結(jié)構(gòu)來(lái)接收,然后不同接口的數(shù)據(jù)部分用不同的 key 來(lái)讀取。可以實(shí)現(xiàn),但總覺(jué)得不夠優(yōu)雅。

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

主要看了兩個(gè)庫(kù):

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

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

以下分別截取兩個(gè)庫(kù)的兩個(gè)部門(mén)管理相關(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;

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

實(shí)現(xiàn)

那接下來(lái)我們直接參照 wecom-sdk 里的實(shí)現(xiàn)方式,寫(xiě)一個(gè)泛型類(lèi),就可以用來(lái)接收企微的不同接口返回的數(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 庫(kù)里的 @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 注解里添加。

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

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

相關(guān)文章

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

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

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

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

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

    Java中API的使用方法詳情

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

    Spring中@Async用法詳解及簡(jiǎn)單實(shí)例

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

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

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

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

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

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

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

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

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

    實(shí)例講解Java 自旋鎖

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

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

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

最新評(píng)論

余干县| 建平县| 平远县| 恩施市| 尤溪县| 宁阳县| 沛县| 上林县| 余姚市| 施秉县| 嘉荫县| 寿光市| 大荔县| 伊宁县| 黑水县| 剑川县| 穆棱市| 定州市| 广西| 察隅县| 盖州市| 山阴县| 芒康县| 雷波县| 股票| 普宁市| 瑞丽市| 贺兰县| 德安县| 东乡族自治县| 隆林| 蒙城县| 易门县| 定西市| 湖南省| 绥阳县| 梁平县| 彭山县| 治多县| 香港 | 辽中县|