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

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自學(xué)書籍推薦 程序員到架構(gòu)師必看的書

    Java自學(xué)書籍推薦 程序員到架構(gòu)師必看的書

    這篇文章主要為大家推薦了Java程序員到架構(gòu)師自學(xué)書籍,幫助大家不斷提高自己的專業(yè)水平,感興趣的小伙伴們可以參考一下
    2016-09-09
  • mybatis中大批量數(shù)據(jù)插入解析

    mybatis中大批量數(shù)據(jù)插入解析

    這篇文章主要介紹了mybatis中大批量數(shù)據(jù)插入解析,使用Mybatis框架批量插入的3種方法,分別是多次調(diào)用insert方法、foreach標簽、batch模式,本文來詳細說明一下,需要的朋友可以參考下
    2024-01-01
  • Java實現(xiàn)記事本功能

    Java實現(xiàn)記事本功能

    這篇文章主要為大家詳細介紹了Java實現(xiàn)記事本功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 使用CORS實現(xiàn)JavaWeb跨域請求問題的方法

    使用CORS實現(xiàn)JavaWeb跨域請求問題的方法

    這篇文章主要介紹了使用Cors實現(xiàn)JavaWeb跨域請求問題的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • 淺析Java中并發(fā)工具類的使用

    淺析Java中并發(fā)工具類的使用

    在JDK的并發(fā)包里提供了幾個非常有用的并發(fā)工具類。CountDownLatch、CyclicBarrier和Semaphore工具類提供了一種并發(fā)流程控制的手段,Exchanger工具類提供了在線程間交換數(shù)據(jù)的一種方法。本文主要介紹了它們的使用,需要的可以參考一下
    2022-12-12
  • Java中的可重入鎖ReentrantLock簡析

    Java中的可重入鎖ReentrantLock簡析

    這篇文章主要介紹了Java中的可重入鎖ReentrantLock簡析,可重入是指同一個線程如果首次獲得了這把鎖,那么因為它是這把鎖的擁有者,因此有權(quán)利再次獲取這把鎖如果是不可重入鎖,那么第二次獲得鎖時,自己也會被鎖擋住,需要的朋友可以參考下
    2023-12-12
  • springboot 中 inputStream 神秘消失之謎(終破)

    springboot 中 inputStream 神秘消失之謎(終破)

    這篇文章主要介紹了springboot 中 inputStream 神秘消失之謎,為了能夠把這個問題說明,我們首先需要從簡單的http調(diào)用說起,通過設(shè)置body等一些操作,具體實現(xiàn)代碼跟隨小編一起看看吧
    2021-08-08
  • Spring boot webService使用方法解析

    Spring boot webService使用方法解析

    這篇文章主要介紹了Spring boot webService使用方法解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • java 設(shè)計模式(DAO)的實例詳解

    java 設(shè)計模式(DAO)的實例詳解

    這篇文章主要介紹了java 設(shè)計模式(DAO)的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • mybatis-plus主鍵生成策略

    mybatis-plus主鍵生成策略

    這篇文章主要介紹了mybatis-plus主鍵生成策略,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評論