求教 Java 里面用 gson 来解析 变化的 api 响应 的比较好的写法。。。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dreamramon
V2EX    问与答

求教 Java 里面用 gson 来解析 变化的 api 响应 的比较好的写法。。。

  •  
  •   dreamramon 2022-08-25 11:47:00 +08:00 1584 次点击

    这是一个创建于 1144 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目里面一直在用 gson 来序列化对象,最近在接一家第三方 api 。

    如果请求出错,对方响应类似:

    {"code":-1021,"msg":"Timestamp for this request is outside of the recvWindow."} 

    请求正确,对方响应:

    { "feeTier": 0, "updateTime": 0, "assets": [{ "asset": "XXX", "updateTime": 0 }], "positions": [{ "symbol": "XXX", "initialMargin": "0", "maintMargin": "0" }] } 

    我自己构造了 2 个对象的 Pojo ,一个是 ResponseError ,一个是 Response

     if( httpResponse.contains("code\":-1021")){ ResponseError resp = GSON.fromJson( httpResponse, ResponseError.class); }else{ Response resp = GSON.fromJson( httpResponse, Response.class); } 

    不知道有没有更好的写法,能够定义一个更好的: 1 ,让我能够不先用 string 来判断。。。 2 ,最好 2 个响应的序列化的对象可以怎样继承一下,统一的返回给上层。。。

    13 条回复    2022-08-26 17:18:21 +08:00
    qping
        1
    qping  
       2022-08-25 13:12:35 +08:00
    正则先 match 下?
    JxQg597
        2
    JxQg597  
       2022-08-25 13:18:57 +08:00
    对方的返回接口不标准,你的接受实体也没办法标准化抽象。
    1.用一个 Response 接收返回值,包含错误响应的 code,msg ,也包含正确响应的所有返回值。
    2.响应直接解析成 Response ,并作解析异常捕获,并抛出异常信息。
    3.根据 code 是否为 null 来判断请求是否错误,并抛出异常信息。
    4.最后直接 return Response
    bk201
        3
    bk201  
       2022-08-25 13:29:45 +08:00
    直接解析 json object 通过 path 拿自己需要的值,放入自己定义的标准 vo 里,返回给内部使用者
    superliy
        4
    superliy  
       2022-08-25 13:38:24 +08:00
    把出错的请求字段放到 abstract response 里,其他正确的 response 继承,这样都只要返回 response 就行,使用时判断 code
    jiajianjava
        5
    jiajianjava  
       2022-08-25 13:48:09 +08:00
    {
    "code":200,
    "msg": "",
    "feeTier": 0,
    "updateTime": 0,
    "assets": [{
    "asset": "XXX",
    "updateTime": 0
    }],
    "positions": [{
    "symbol": "XXX",
    "initialMargin": "0",
    "maintMargin": "0"
    }]
    }

    直接合并,定义这样是不是就好了?
    dreamramon
        6
    dreamramon  
    OP
       2022-08-25 14:05:34 +08:00
    @jiajianjava #5
    @JxQg597 #2
    主要是他正确的响应,他有几十个 api ,就有几十个格式。。。
    我们现在有 ResponseError.class, ResponseA.class, ResponseB.class
    然后有的时候,因为对方 api 不稳定,请求有需要重试。。。
    以前,只需要在我们封装的 HttpUtil 里面根据网络状态或者 http 状态码自动重试,业务层不操心了。。。

    但是现在这家,需要在业务层重试。。。所以说,想能不能有个统一的手段,能解析成一个 response ,然后根据里面某个值的判断,再分开能拿到 ResponseA 或者 ResponseB 。
    fgwmlhdkkkw
        7
    fgwmlhdkkkw  
       2022-08-25 14:54:23 +08:00
    try,catch
    JxQg597
        8
    JxQg597  
       2022-08-25 15:24:04 +08:00
    @dreamramon #6
    ```java
    class ResponseBase{
    String code,
    String msg
    }
    class XXXResponse extends ResponseBase{
    xxx,
    xxx,
    xxx
    }
    XXXResponse getXXX(AtomicInteger retriesNum){
    if (retriesNum==null ) retriesNum = new AtomicInteger(0);
    XXXResponse respOnse= doGet();
    if(response.getcode !=null){
    log.error;
    int currentNum = retriesNum.getAndIncrement();
    if(currentNum>configRetriesNum) throw Exception;
    #需要延迟 sleep?
    return getXXX(retriesNum);
    }
    return response ;
    }
    ```
    JNotEnoughW
        9
    JNotEnoughW  
       2022-08-25 15:43:16 +08:00
    自己包装一层转换器,提前校验是否有 "code",组装成统一格式返回
    {
    "code":200,
    "msg":"",
    "data":xxx
    }
    luman
        10
    luman  
       2022-08-25 15:48:19 +08:00
    https://gist.github.com/sunluman/b49e12aa3e4f76390fbc08504ef38345
    只能通过有哪些 key 来区分用什么实体类型?可以先类似这样封装下,然后怒喷下对面
    itechify
        11
    itechify  
    PRO
       2022-08-25 23:15:02 +08:00 via Android
    造轮子的时间到了,最近对接某平台也这样,不过会有固定 code 表示请求失败和正确
    dreamramon
        12
    dreamramon  
    OP
       2022-08-26 16:30:52 +08:00
    @JxQg597 #8

    谢谢大神。。。我的想法是有没有可能,可以写一个统一的父累。

    Response resp = GSON.fromJson( httpResponse, Response.class);
    然后 return 这个 resp 给到业务的方法,然后业务的方法拿到了这个 resp ,可以根据里面的 code 来判断是否出错,并且解析出自己的 ResponseA ,或者 ResponseB?

    比如:
    业务 A:
    if (resp.code==null) {
    ResponseA respA= (ResponseA) resp.data;

    }else if (resp.code == -1021) {
    //retry logic
    }


    业务 B:

    业务 A:
    if (resp.code==null) {
    ResponseB respB= (ResponseB) resp.data;

    } else if (resp.code == -1021) {
    //业务 B -1021 不重试
    } else if (resp.code == -1001) {
    //业务 B -1001 重试,下面自己实现重试逻辑
    }
    JxQg597
        13
    JxQg597  
       2022-08-26 17:18:21 +08:00
    @dreamramon #12 可以参考 9 楼的做法,做成标准 Response<T>,解析两次 Json ,需要用到泛型。
    ```java
    Class Response<T>{
    private String code;
    private String msg;
    private T data;
    public Response<T>(T data){
    this.data = data;
    }
    }
    public <T> Response<T> invokeGet(XXXQuery query, Class<T> tClass){
    try{
    String respOnseJson= doGet(query);
    Response respOnse= JSONUtil.toBean(responseJson,Response.class);
    if(StrUtil.isNotEmpty(response.getCode())){
    return response;
    }
    T datd = JSONUtil.toBean(responseJson,tClass);
    return new Response<T>(data);
    }catch(AnyException e){
    log.error;
    throw new BussniessException();
    }
    }
    ```
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5864 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 03:22 PVG 11:22 LAX 20:22 JFK 23:22
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86