json转实体,json转List实体,json转泛型实体

1、=========================

https://segmentfault.com/a/1190000009523164

package com.thunisoft.maybee.engine.utils;

import com.google.gson.Gson;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * Json2Bean / Json2List / Json2List<T>
 *
 * @author hcq
 */
public class GsonUtil {

    private GsonUtil() {

    }

    /**
     * Json 转为 bean
     *
     * @param json
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T bean4Json(String json, Class<T> type) {
        Gson gson = new Gson();
        return gson.fromJson(json, type);

    }

    /**
     * Json 转为 List<bean>
     *
     * @param json
     * @param typeclazz
     * @param <T>
     * @return
     */
    public static <T> List<T> list4Json(String json, Class<T> typeclazz) {
        ParameterizedTypeImpl type = new ParameterizedTypeImpl(typeclazz);
        Gson gson = new Gson();
        return gson.fromJson(json, type);
    }

    /**
     * 参数类型转换
     */
    private static class ParameterizedTypeImpl implements ParameterizedType {
        private Class clazz;

        public ParameterizedTypeImpl(Class clz) {
            clazz = clz;
        }

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

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

        public Type getOwnerType() {
            return null;
        }
    }

    public static void main(String[] args) {

        String json1 = "{"id":1,"name":"eric"}";
        String json2 = "[{"id":1,"name":"eric"},{"id":2,"name":"john"}]";
        String json3 = "{"page":1,"size":10,"total":2,"data":[{"id":1,"name":"eric"},{"id":2,"name":"john"}]}";

        String helloworld = "helloworld!";
        String bl = "false";
        String integer = "123";
        String db = "23423d";

        User user = GsonUtil.bean4Json(json1, User.class);
        List<User> lists = GsonUtil.list4Json(json2, User.class);
        Page<User> page = GsonUtil.bean4Json(json3, Page.class);

        String res1 = GsonUtil.bean4Json(helloworld, String.class);
        Boolean res2 = GsonUtil.bean4Json(bl, Boolean.class);
        Integer res3 = GsonUtil.bean4Json(integer, Integer.class);
        Double res4 = GsonUtil.bean4Json(db, Double.class);

        System.out.println("user:" + user);
        System.out.println("lists:" + lists);
        System.out.println("page:" + page);

        User user1 = lists.get(0);
        System.out.println("user1:" + user1);

        System.out.println("===");

        System.out.println(res1);
        System.out.println(res2);
        System.out.println(res3);
        System.out.println(res4);
    }

    private class Page<T> {
        private int page;

        private int size;

        private int total;

        private List<T> data;

        public int getPage() {
            return page;
        }

        public void setPage(int page) {
            this.page = page;
        }

        public int getSize() {
            return size;
        }

        public void setSize(int size) {
            this.size = size;
        }

        public int getTotal() {
            return total;
        }

        public void setTotal(int total) {
            this.total = total;
        }

        public List<T> getData() {
            return data;
        }

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

        @Override
        public String toString() {
            return "User [page=" + page + ", size=" + size + ", total=" + total + ", data=" + data + "]";
        }
    }

    private class User {
        private int id;

        private String name;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

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

        @Override
        public String toString() {
            return "User [id=" + id + ", name=" + name + "]";
        }
    }
}

  

2/=========================

https://www.jianshu.com/p/701ae370f959

通常情况下,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,而是LinkedTreeMap,LinkedTreeMap是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就行了。

<div align ="right">写于 9/7/2017 4:52:27 PM</div>

作者:orzangleli
链接:https://www.jianshu.com/p/701ae370f959
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
原文地址:https://www.cnblogs.com/hfultrastrong/p/9263932.html