Gson字符串数组转成List对象(包括泛型操作)

通常情况下,Server端返回的json数据应该可以一次性完全解析,但是要是遇到server返回的json里又包含json字符串就得自己再手动解析一次了。

我们知道json字符串解析成模型类型很简单,但是如果要把json数组字符串解析List对象,应该怎么办呢?

举一个实际的例子:

[
    {
        "name": "zhaoxa",
        "score": 100
    },
    {
        "name": "zhaoxa2",
        "score": 76
    },
    {
        "name": "zhaoxa3",
        "score": 99
    },
    {
        "name": "zhaoxa4",
        "score": 48
    }
]

根据这个json字符串列表,我们设计名为Student的数据模型,Parcelable接口可以使用AS插件一键生成:

public class Student implements Parcelable{
    String name;
    int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.score);
    }

    protected Student(Parcel in) {
        this.name = in.readString();
        this.score = in.readInt();
    }

    public static final Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel source) {
            return new Student(source);
        }

        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
}

现在开始着手解析这个json数组字符串。

1. 先转成数组,再转成List

最常规的方法把jsonString转化为T[]数组,然后再使用Arrys.asList将数组转为List。

Student[] array = new Gson().fromJson(jsonString,Student[].class);
List<Student> list = Arrays.asList(array);
Log.i("lxc"," ---> " + list);

通过断点,可以看到list下面的数据已经转为Student类型了。

2. 使用TypeToken进行转化

Type type = new TypeToken<List<Student>>(){}.getType();
List<Student> list = new Gson().fromJson(jsonString,type);

3. 如何使用泛型抽象

假设不只一个json数组字符串需要你解析,很显然重复的代码应该抽象成一个方法。

假设现在有关于书籍的信息,json数组内容如下:

[
    {
        "author": "zhaoxa",
        "name": "如何入门android",
        "price": 100
    },
    {
        "author": "zhaoxa2",
        "name": "如何入门android2",
        "price": 76
    },
    {
        "author": "zhaoxa3",
        "name": "如何入门android3",
        "price": 99
    },
    {
        "author": "zhaoxa4",
        "name": "如何入门android4",
        "price": 48
    }
]

同样的,我们得新建一个Book类,难道必须得复制之前的代码进行操作么?能不能抽象一个泛型的方法出来,把json数组字符串转化成类。

好的,应该可以的,我们进行以下尝试:

  • 第一次尝试

报错了,fromJson不支持使用泛型解析。

  • 第二次尝试
public <T> List<T> parseString2List(String json) {
        Type type = new TypeToken<List<T>>(){}.getType();
        List<T> list = new Gson().fromJson(jsonString,type);
        return list;
    }

嗯,没有报错,我们运行时断点看看list里的数据类型。

我们通过这句话调用方法:

List<Student> list = parseString2List(jsonString);

可以看到,list中的数据类型不是Student,而是LinkedTreeMapLinkedTreeMap是Gson库内部数据模型,换句话说我们的解析失败了,尝试着将parseString2List方法中的泛型T去掉,运行结果一样,说明Gson解析时不支持泛型。

真的就没有办法了么,难道解析数组json必须得重复调用相似的代码?嗯,在接触ParameterizedType接口之前,你应该很难实现这个功能。但是现在知道了ParameterizedType接口,我们就有了第三次尝试。

  • 第三次尝试
    public <T> List<T> parseString2List(String json,Class clazz) {
        Type type = new ParameterizedTypeImpl(clazz);
        List<T> list =  new Gson().fromJson(json, type);
        return list;
    }

    private  class ParameterizedTypeImpl implements ParameterizedType {
        Class clazz;
        
        public ParameterizedTypeImpl(Class clz) {
            clazz = clz;
        }

        @Override
        public Type[] getActualTypeArguments() {
            return new Type[]{clazz};
        }

        @Override
        public Type getRawType() {
            return List.class;
        }

        @Override
        public Type getOwnerType() {
            return null;
        }
    }

在调用的地方使用:

List<Student> list = parseString2List(jsonString, Student.class);
List<Book> list2 = parseString2List(jsonString, Book.class);

断点查看解析结果,嗯,完美解析~

好的,现在在回过头来看看,ParameterizedType的几个方法的含义吧,以HashMap<String,Integer>为例。

  • getActualTypeArguments 返回实际类型组成的数据,即new Type[]{String.class,Integer.class}

  • getRawType 返回原生类型,即 HashMap

  • getOwnerType 返回 Type 对象,表示此类型是其成员之一的类型。例如,如果此类型为 O<T>.I<S>,则返回 O<T> 的表示形式。 如果此类型为顶层类型,则返回 null。这里就直接返回null就行了。

要从Redis中获取JSON数组对象并将其转换为泛型列表,您可以按照以下步骤进行操作: 1. 从Redis中获取JSON字符串。 2. 使用适当的库(如Gson或Jackson)将JSON字符串转换为Java对象。 3. 通过使用Java的类型引用(TypeReference)来指定您要转换的泛型类型。 4. 使用适当的库将嵌套的JSON数组对象转换为嵌套的泛型列表。 下面是一个示例代码片段,演示如何完这个过程: ```java import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; // 从Redis中获取JSON字符串 String jsonArrayString = jedis.get("yourKey"); // 使用Jackson库将JSON字符串转换为Java对象 ObjectMapper objectMapper = new ObjectMapper(); List<YourObjectType> yourObjectList = objectMapper.readValue(jsonArrayString, new TypeReference<List<YourObjectType>>(){}); // 如果存在嵌套的列表,您可以使用递归来转换它们 for (YourObjectType yourObject : yourObjectList) { List<YourNestedObjectType> yourNestedObjectList = objectMapper.convertValue(yourObject.getNestedList(), new TypeReference<List<YourNestedObjectType>>(){}); yourObject.setNestedList(yourNestedObjectList); } // 现在,您可以使用泛型列表进行进一步处理 for (YourObjectType yourObject : yourObjectList) { // 处理您的泛型对象 } ``` 请注意,这只是一个示例代码片段,您需要根据您的实际情况进行适当的修改和调整。另外,您需要将代码中的"yourKey"、"YourObjectType"和"YourNestedObjectType"替换为合适的值和类型。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值