Normally, the json data returned by the Server should be fully parsed at once, but if the JSON returned by the Server contains a JSON string, you have to manually parse it again.

We know it’s easy to parse json strings into model types, but what if we want to parse A JSON array string into a List object?

Here’s a practical example:

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

From this LIST of JSON strings, we design a data model named Student that the Parcelable interface can generate with one click using the AS plugin:

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

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

    public String getName(a) {
        return name;
    }

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

    public int getScore(a) {
        return score;
    }

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

    @Override
    public int describeContents(a) {
        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 newStudent[size]; }}; }Copy the code

Now start parsing the JSON array string.

1. Convert first to an array, then to a List

The most common method is to convert jsonString to a T[] array and then use arrys.asList to convert the array to a List.

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

From the breakpoint, you can see that the data below the list has been converted to Student.





2. Use TypeToken for conversion

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




3. How to use generic abstractions

Given that more than one JSON array string needs to be parsed, it’s obvious that repetitive code should be abstracted into a method.

Suppose we now have information about the book, and the json array looks like this:

[{"author": "zhaoxa"."name": "How to Get Started with Android"."price": 100
    },
    {
        "author": "zhaoxa2"."name": "How to get started with android2"."price": 76
    },
    {
        "author": "zhaoxa3"."name": "How to get started with android3"."price": 99
    },
    {
        "author": "zhaoxa4"."name": "How to get started on android4"."price": 48}]Copy the code

Similarly, we have to create a new Book class, do we have to copy the previous code to operate? Can abstract a generic method out of the JSON array string into a class.

Ok, it should work. Let’s try the following:

  • First try




FromJson does not support generic parsing.

  • Second attempt
public <T> List<T> parseString2List(String json) {
        Type type = new TypeToken<List<T>>(){}.getType();
        List<T> list = new Gson().fromJson(jsonString,type);
        return list;
    }
Copy the code

Well, no error, let’s run the breakpoint to see the data types in the list.

We call the method with this statement:

List<Student> list = parseString2List(jsonString);

As you can see, the data type in the list is not Student, but LinkedTreeMap, which is the internal data model of the Gson library. In other words, we failed to parse. We tried to remove the generic T from the parseString2List method. Note Gson does not support generics.





Is there really no way to parse the array JSON without repeatedly calling similar code? Well, you should have a hard time implementing this functionality until you get to the ParameterizedType interface. But now that we know about the ParameterizedType interface, we have a third try.

  • Third attempt
    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(a) {
            return List.class;
        }

        @Override
        public Type getOwnerType(a) {
            return null; }}Copy the code

Use:

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

Breakpoint to view the parsing result, HMM, perfect parsing ~









Ok, so let’s go back and look at some of the methods on ParameterizedType, using HashMap<String,Integer> as an example.

  • GetActualTypeArguments return the actual Type of data, that is, the new Type [] {String class, Integer. The class}

  • GetRawType returns the native type, HashMap

  • GetOwnerType returns a Type object indicating that the Type is a Type of one of its members. For example, if this type is O

    .I
    , the representation O

    is returned. If this type is a top-level type, null is returned. I’m just going to return null here.

<div align =”right”>