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

2022-08-25 11:47:00 +08:00
 dreamramon

项目里面一直在用 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 个响应的序列化的对象可以怎样继承一下,统一的返回给上层。。。

1239 次点击
所在节点    问与答
13 条回复
qping
2022-08-25 13:12:35 +08:00
正则先 match 下?
JxQg597
2022-08-25 13:18:57 +08:00
对方的返回接口不标准,你的接受实体也没办法标准化抽象。
1.用一个 Response 接收返回值,包含错误响应的 code,msg ,也包含正确响应的所有返回值。
2.响应直接解析成 Response ,并作解析异常捕获,并抛出异常信息。
3.根据 code 是否为 null 来判断请求是否错误,并抛出异常信息。
4.最后直接 return Response
bk201
2022-08-25 13:29:45 +08:00
直接解析 json object 通过 path 拿自己需要的值,放入自己定义的标准 vo 里,返回给内部使用者
superliy
2022-08-25 13:38:24 +08:00
把出错的请求字段放到 abstract response 里,其他正确的 response 继承,这样都只要返回 response 就行,使用时判断 code
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
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
2022-08-25 14:54:23 +08:00
try,catch
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
2022-08-25 15:43:16 +08:00
自己包装一层转换器,提前校验是否有 "code",组装成统一格式返回
{
"code":200,
"msg":"",
"data":xxx
}
sunjiayao
2022-08-25 15:48:19 +08:00
https://gist.github.com/sunluman/b49e12aa3e4f76390fbc08504ef38345
只能通过有哪些 key 来区分用什么实体类型?可以先类似这样封装下,然后怒喷下对面
oneisall8955
2022-08-25 23:15:02 +08:00
造轮子的时间到了,最近对接某平台也这样,不过会有固定 code 表示请求失败和正确
dreamramon
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
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();
}
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/875283

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX