泛型解析JSON数据封装

本文介绍如何通过泛型来封装服务器返回的JSON数据,避免接口返回数据格式不一致导致的冗余代码。创建接口返回实体类和封装服务器回调接口,并使用Gson解析数据,提高开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

以下面服务器返回数据格式为例:

{
    "code":200,
    "msg":"成功",
    "data":{
        "userName":"小明",
        "nickName":"一花一世界"
    }
}

在这个返回的JSON数据里面codemsg的类型是固定不变的,但是data的类型却会经常改变。比如这里返回的是User格式的数据,另一个接口返回的可能就是UserInfo格式的数据了。由于各个接口返回的数据格式不同,如果对应的每个接口都进行GSON解析,那么我们的代码将会显得比较臃肿。此时如果有一个统一的封装接口来处理解析返回的数据,不仅会避免大量冗余代码的出现,同时将会大大地提高开发效率。

创建接口返回实体类

public class HttpResult<T> {

    private T data;
    private int code;
    private String msg;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "ServerCallBackModel{" +
                "data=" + data +
                ", code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
}

封装服务器回调接口

1、回调的抽象基类

public abstract class HttpCallBack<T> {

    private Type mGenericSuperclass;

    public HttpCallBack() {
        Type genericSuperclass = getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            mGenericSuperclass = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
        } else {
            mGenericSuperclass = Object.class;
        }
    }

    public abstract void onResolve(T t);

    public abstract void onFailed(int code, String msg);

    public Type getType() {
        return mGenericSuperclass;
    }
}
  1. TypeJava中所有类型的公共高级接口。包括原始类型(对应Class)、参数化类型(对应ParameterizedType)、数组类型(对应GenericArrayType)、类型变量(对应TypeVariable)和基本类型(对应Class)。
  2. getGenericSuperclass():获得带有泛型的父类。
  3. ParameterizedType:参数化类型,即泛型。
  4. getActualTypeArguments():获取参数化类型的数组,泛型参数可能有多个。

getActualTypeArguments()[0]得到泛型的第一个参数T的类型,赋值给当前泛型类型的成员变量genericSuperclass。如果不是参数化类型,比如在接收服务器回调的地方没有加泛型类型,那么我们就给genericSuperclass赋值ObjectClass对象。

其中的抽象方法:

onResolve():用来解析接口返回的json数据,在子类中需要重写它来进行具体解析。
onFailed():错误回调。

2、解析返回数据的抽象子类

public abstract class OnServerCallBack<T, V> extends HttpCallBack<T> {

    @Override
    public void onResolve(T t) {
        if (t instanceof HttpResult) {
            HttpResult<V> callbackData = (HttpResult) t;
            V result = callbackData.getData();
            if (callbackData.getCode() == 200) {
                onSuccess(result);
            } else {
                onFailed(callbackData.getCode(), callbackData.getMsg());
            }
        } else {
            onSuccess((V) t);
        }
    }

    @Override
    public void onFailed(int code, String msg) {
        if (enableShowToast()) {
            ToastUtil.showText(msg);
        } else {
            onFailure(code, msg);
        }
    }

    public abstract void onSuccess(V data);

    public abstract void onFailure(int code, String msg);

    public boolean enableShowToast() {
        return false;
    }
}

这里我们定义了一个抽象带两个类型参数的泛型类,第一个参数是Gson映射的外层对象,比如可以传入我们前面定义的HttpResult;第二个参数就是外层对象中的数据了,比如HttpResult中的data

其中enableShowToast()这个方法主要是用于拦截错误返回,用于统一处理所有请求的错误,默认只判断是否需要直接弹Toast显示错误信息。如果想直接将错误信息弹窗提示,只需要重写enableShowToast方法,返回true即可。

3、不解析返回数据的抽象子类

public abstract class OnCommonCallBack<T> extends HttpCallBack<T> {

    @Override
    public void onResolve(T t) {
        onSuccess(t);
    }

    @Override
    public void onFailed(int code, String msg) {
        if (enableShowToast()) {
            ToastUtil.showText(msg);
        } else {
            onFailure(code, msg);
        }
    }

    public abstract void onSuccess(T data);

    public abstract void onFailure(int code, String msg);

    public boolean enableShowToast() {
        return false;
    }
}

此泛型类用于直接返回Http返回的数据。有些时候我们不需要对Http返回的数据进行解析,这时我们就可以使用此种解析方式来解析。

Gson解析

public class HttpUtils {

    private static Gson mGson;

    public static void getRequest(String url, Map<String, String> params, HttpCallBack callBack) {
        if (callBack == null) {
            return;
        }

        if (mGson == null) {
            mGson = new Gson();
        }

        boolean returnJson = false;
        Type type = callBack.getType();

        if (type instanceof Class) {
            switch (((Class) type).getSimpleName()) {
                case "Object":
                case "String":
                    returnJson = true;
                    break;
                default:
                    break;
            }
        }

        if (returnJson) {
            try {
                callBack.onResolve(url);
            } catch (Exception e) {
                callBack.onFailed(-1, e.getMessage());
                e.printStackTrace();
            }
        } else {
            try {
                callBack.onResolve(mGson.fromJson(url, type));
            } catch (Exception e) {
                callBack.onFailed(-1, e.getMessage());
                e.printStackTrace();
            }
        }
    }
}

Http请求成功返回数据之后,首先判断泛型类型type是不是Class类型,如果是则判断type的名字是否为String或者Object,是则直接在成功回调中传入返回的json字符串。如果不是则用Gsonjson数据解析出来,实参就是type

使用

//解析Http返回的Json数据,返回data字段中封装的内容
showModel.ShowUser(Constant.object1, null, new OnServerCallBack<HttpResult<User>, User>() {
    @Override
    public void onSuccess(User data) {
        LogUtil.e("ShowUser-->" + data.toString());
    }

    @Override
    public void onFailure(int code, String msg) {
        LogUtil.e("ShowUser failure-->" + code + " : " + msg);
    }
});

//不解析Http返回的Json数据,返回Http返回的内容
showModel.ShowStringData(Constant.object1, null, new OnCommonCallBack<String>() {
    @Override
    public void onSuccess(String data) {
        LogUtil.e("ShowStringData-->" + data);
    }

    @Override
    public void onFailure(int code, String msg) {
        LogUtil.e("ShowStringData failure-->" + code + " : " + msg);
    }
});

至此我们就可以按需解析服务器返回的数据了。

项目地址 ☞ 传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值