您当前的位置:首页 > 生活热点 > 正文

json是什么 如何在服务端解析json

json是什么 如何在服务端解析json前言接入某业务接口时,发现其成功和失败状态下,data字段的数据类型并不一致。接口已上线多时无法随便改动,故需要客户端自己兼容请求成功时,data是T类型(某自定义数据类型){ "code" : 0,

前言

json是什么 如何在服务端解析jsonjson是什么 如何在服务端解析json

接入某业务接口时,发现其成功和失败状态下,data字段的数据类型并不一致。

接口已上线多时无法随便改动,故需要客户端自己兼容

请求成功时,data是T类型(某自定义数据类型)

{ "code" : 0, "data" : {} }

请求失败时,data是String类型

{ "code" : 1000, "data" : "错误信息" }

一个data字段对应了两种数据类型,只能把它定义成Object类型。请求成功时,由于data定义成Object类型,默认情况下Gson会将其解析成LinkedTreeMap。使用时需要从map中用key来取值,极其不方便。

另辟蹊径

既然将data定义成Object类型极其不方便,那么data就只能定义成T类型了。但是这样的话,请求失败时解析又会抛出异常(因为此时data为String类型)。

能否做到请求成功时,将data解析成T类型,而其它情况不解析data或者将data的值挪到别的字段中(如message字段)?个人更倾向于后者的想法。也就是能否将请求失败时的JSON修改成以下格式?

{ "code" : 1000, "data" : null, "message" : "错误信息" }

实现方案

基于上述思路,我想到了两种做法

自定义OkHttp的Interceptor

自定义Gson的TypeAdapter

自定义Interceptor

简单说下做法

只拦截某(几)个接口

从Response中读取并解析JSON

根据code判断是否请求成功

如果请求失败则生成新的JSON,并返回新的Response

这种做法个人感觉使用比较繁琐,而且需额外解析JSON。具体做法可以看下这篇文章Android 优雅地处理后台返回的骚数据

自定义TypeAdapter

如何使用TypeAdapter修改JSON结构呢?经过一番搜索之后,我在stackoverflow上找到了想要的答案。根据上述回答的实现,我稍微修改了一下

public class CustomizedTypeAdapterFactory<C> implements TypeAdapterFactory { private final Class<C> mClass; public CustomizedTypeAdapterFactory(Class<C> cls) { this.mClass = cls; } @Override public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { //noinspection unchecked return type.getRawType() == mClass ? (TypeAdapter<T>) createAdapter(gson, (TypeToken<C>) type) : null; } private TypeAdapter<C> createAdapter(Gson gson, TypeToken<C> type) { // 获取Gson中该类型对应的TypeAdapter final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type); return new TypeAdapter<C>() { @Override public void write(JsonWriter out, C value) throws IOException { // 将value转换成JSON树并将其序列化 JsonElement tree = delegate.toJsonTree(value); onWrite(value, tree); Streams.write(tree, out); } @Override public C read(JsonReader in) throws IOException { // 将读取的JSON串反序列化JSON树 JsonElement tree = Streams.parse(in); onRead(tree); return delegate.fromJsonTree(tree); } }; } protected void onWrite(C value, JsonElement json) { } protected void onRead(JsonElement json) { } }

继承上述TypeAdapterFactory,重写onWrite和onRead方法,就可以实现在序列化和反序列化之前修改JSON的的功能。

public class BaseResponse<T> { private int code; private T data; private String message; // 新增字段 ... } public class ResponseTypeAdapterFactory extends CustomizedTypeAdapterFactory<BaseResponse> { private static final String CODE_OK = "0"; public static final String DATA = "data"; public static final String CODE = "code"; public static final String MSG = "message"; public ResponseTypeAdapterFactory() { super(BaseResponse.class); } @Override protected void onRead(JsonElement json) { JsonObject jsonObject = json.getAsJsonObject(); JsonElement code = jsonObject.get(CODE);// 获取code字段 // 调用成功,不处理 if (code == null || !code.isJsonPrimitive() || CODE_OK.equals(code.getAsString())) { return; } JsonElement data = jsonObject.get(DATA); if (data != null) { // 将data的值挪到message中 jsonObject.remove(DATA); jsonObject.add(MSG, data); } } }

自定义一个ResponseTypeAdapterFactory,专门用于解析BaseResponse这种类型。因为只需要修改反序列化的JSON结构,所以只重写了onRead方法。onRead方法的逻辑也很简单。简单说下就是获取code字段,判断是否请求失败,如果是则将data的值挪到message中。

最后,别忘记将ResponseTypeAdapterFactory注册到Gson,还有配置混淆规则!!

Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new ResponseTypeAdapterFactory()) .create();

总结

利用Gson的TypeAdapter,实现了根据code来修改JSON结构的功能,从而达到动态解析JSON的效果。使用本方案可以很好地解决JSON结构不一致的问题。题外话,遇到JSON结构不一致的问题,务必先与后台同事沟通沟通再沟通!!!


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 画死亡兔子(简笔画兔子折颈而死)

下一篇: 元宵节绝美诗词,你最喜欢哪一首诗,元宵节绝美诗词,你最喜欢哪一首古诗



推荐阅读