Gson、Fastjson解析里的Type,如何用一个方法解析所有数据

使用Gson或者fastjson解析数据,我们的梦想是用一套方法解析所有数据:

public T parse(String jsonStr,Class clazz)

但这只能是想想,比如上面的方法,list类型就没法处理了

解析object和list,肯定得分开俩方法写,想用一个方法的话就得手动传Type。Gson和fastjson之类都有生成Type的辅助类TypeToken 和TypeReference。

TypeToken 和TypeReference都是辅助生成Type的工具类(大概是这样,没仔细研究过),其实这个是可以自己写方法实现的,目标是一个方法来解析所有的数据。参考鸿祥大神的一部分代码和抄袭Gson的部分源码,抽出一个生成Type的类,支持object和list,代码不多两三百行,源码其实我也不懂,只是根据需要抽出来的,

1.获取Type使用如下:

//普通object
Type type = new ParseType() {}.getType();
//列表list
Type type = new ParseType>() {}.getType();
//复杂的
Type type = new ParseType>>() {}.getType();

//解析
User user =  JSON.parseObject(jsonString,type);  //fastjson
User user = gson.fromJson(jsonString, type);        //gson

NetReslult> netResult = JSON.parseObject(jsonString, type);
NetReslult> netResult = gson.fromJson(jsonString, type);
ps:注意new出来的是ParseType之类的对象 new ParseType() {},通过泛型这种方式来获取Type类型必须用子类的对象,看清楚了,所有new的ParseType后面都有{}所以生成的是子类的对象。

2.ParseType源码:

public class ParseType {


    public Type mType;

    public ParseType() {
        mType = getSuperclassTypeParameter(getClass());
    }


    public Type getType() {
        return mType;
    }

    static Type getSuperclassTypeParameter(Class subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return canonicalize(parameterized.getActualTypeArguments()[0]);
    }


    static Type canonicalize(Type type) {
        if (type instanceof Class) {
            Class c = (Class) type;
            return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;

        } else if (type instanceof ParameterizedType) {
            ParameterizedType p = (ParameterizedType) type;
            return new ParameterizedTypeImpl(p.getOwnerType(),
                    p.getRawType(), p.getActualTypeArguments());

        } else if (type instanceof GenericArrayType) {
            GenericArrayType g = (GenericArrayType) type;
            return new GenericArrayTypeImpl(g.getGenericComponentType());

        } else if (type instanceof WildcardType) {
            WildcardType w = (WildcardType) type;
            return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());

        } else {
            // type is either serializable as-is or unsupported
            return type;
        }
    }


    private static final class GenericArrayTypeImpl implements GenericArrayType, Serializable {
        private final Type componentType;

        public GenericArrayTypeImpl(Type componentType) {
            this.componentType = canonicalize(componentType);
        }

        public Type getGenericComponentType() {
            return componentType;
        }

        @Override public boolean equals(Object o) {
            return o instanceof GenericArrayType
                    && $equals(this, (GenericArrayType) o);
        }

        @Override public int hashCode() {
            return componentType.hashCode();
        }

        @Override public String toString() {
            return typeToString(componentType) + "[]";
        }

        private static final long serialVersionUID = 0;
    }


    private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable {
        private final Type ownerType;
        private final Type rawType;
        private final Type[] typeArguments;

        public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
            // require an owner type if the raw type needs it
            if (rawType instanceof Class) {
                Class rawTypeAsClass = (Class) rawType;
                boolean isStaticOrTopLevelClass = Modifier.isStatic(rawTypeAsClass.getModifiers())
                        || rawTypeAsClass.getEnclosingClass() == null;
                checkArgument(ownerType != null || isStaticOrTopLevelClass);
            }

            this.ownerType = ownerType == null ? null : canonicalize(ownerType);
            this.rawType = canonicalize(rawType);
            this.typeArguments = typeArguments.clone();
            for (int t = 0, length = this.typeArguments.length; t < length; t++) {
                checkNotNull(this.typeArguments[t]);
                checkNotPrimitive(this.typeArguments[t]);
                this.typeArguments[t] = canonicalize(this.typeArguments[t]);
            }
        }

        public Type[] getActualTypeArguments() {
            return typeArguments.clone();
        }

        public Type getRawType() {
            return rawType;
        }

        public Type getOwnerType() {
            return ownerType;
        }

        @Override public boolean equals(Object other) {
            return other instanceof ParameterizedType
                    && $equals(this, (ParameterizedType) other);
        }

        @Override public int hashCode() {
            return Arrays.hashCode(typeArguments)
                    ^ rawType.hashCode()
                    ^ hashCodeOrZero(ownerType);
        }

        @Override public String toString() {
            int length = typeArguments.length;
            if (length == 0) {
                return typeToString(rawType);
            }

            StringBuilder stringBuilder = new StringBuilder(30 * (length + 1));
            stringBuilder.append(typeToString(rawType)).append("<").append(typeToString(typeArguments[0]));
            for (int i = 1; i < length; i++) {
                stringBuilder.append(", ").append(typeToString(typeArguments[i]));
            }
            return stringBuilder.append(">").toString();
        }

        private static final long serialVersionUID = 0;
    }

    private static final class WildcardTypeImpl implements WildcardType, Serializable {

        static final Type[] EMPTY_TYPE_ARRAY = new Type[] {};

        private final Type upperBound;
        private final Type lowerBound;

        public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) {
            checkArgument(lowerBounds.length <= 1);
            checkArgument(upperBounds.length == 1);

            if (lowerBounds.length == 1) {
                checkNotNull(lowerBounds[0]);
                checkNotPrimitive(lowerBounds[0]);
                checkArgument(upperBounds[0] == Object.class);
                this.lowerBound = canonicalize(lowerBounds[0]);
                this.upperBound = Object.class;

            } else {
                checkNotNull(upperBounds[0]);
                checkNotPrimitive(upperBounds[0]);
                this.lowerBound = null;
                this.upperBound = canonicalize(upperBounds[0]);
            }
        }

        public Type[] getUpperBounds() {
            return new Type[] { upperBound };
        }

        public Type[] getLowerBounds() {
            return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY;
        }

        @Override public boolean equals(Object other) {
            return other instanceof WildcardType
                    && $equals(this, (WildcardType) other);
        }

        @Override public int hashCode() {
            // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds());
            return (lowerBound != null ? 31 + lowerBound.hashCode() : 1)
                    ^ (31 + upperBound.hashCode());
        }

        @Override public String toString() {
            if (lowerBound != null) {
                return "? super " + typeToString(lowerBound);
            } else if (upperBound == Object.class) {
                return "?";
            } else {
                return "? extends " + typeToString(upperBound);
            }
        }

        private static final long serialVersionUID = 0;
    }



    public static  T checkNotNull(T obj) {
        if (obj == null) {
            throw new NullPointerException();
        }
        return obj;
    }

    public static void checkArgument(boolean condition) {
        if (!condition) {
            throw new IllegalArgumentException();
        }
    }

    public static String typeToString(Type type) {
        return type instanceof Class ? ((Class) type).getName() : type.toString();
    }

    static int hashCodeOrZero(Object o) {
        return o != null ? o.hashCode() : 0;
    }

    static void checkNotPrimitive(Type type) {
        boolean conmdition = !(type instanceof Class) || !((Class) type).isPrimitive();
        if(!conmdition){
            throw new IllegalArgumentException();
        }
    }


    static boolean $equal(Object a, Object b) {
        return a == b || (a != null && a.equals(b));
    }

    public static boolean $equals(Type a, Type b) {
        if (a == b) {
            // also handles (a == null && b == null)
            return true;

        } else if (a instanceof Class) {
            // Class already specifies equals().
            return a.equals(b);

        } else if (a instanceof ParameterizedType) {
            if (!(b instanceof ParameterizedType)) {
                return false;
            }

            // TODO: save a .clone() call
            ParameterizedType pa = (ParameterizedType) a;
            ParameterizedType pb = (ParameterizedType) b;
            return $equal(pa.getOwnerType(), pb.getOwnerType())
                    && pa.getRawType().equals(pb.getRawType())
                    && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments());

        } else if (a instanceof GenericArrayType) {
            if (!(b instanceof GenericArrayType)) {
                return false;
            }

            GenericArrayType ga = (GenericArrayType) a;
            GenericArrayType gb = (GenericArrayType) b;
            return $equals(ga.getGenericComponentType(), gb.getGenericComponentType());

        } else if (a instanceof WildcardType) {
            if (!(b instanceof WildcardType)) {
                return false;
            }

            WildcardType wa = (WildcardType) a;
            WildcardType wb = (WildcardType) b;
            return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds())
                    && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds());

        } else if (a instanceof TypeVariable) {
            if (!(b instanceof TypeVariable)) {
                return false;
            }
            TypeVariable va = (TypeVariable) a;
            TypeVariable vb = (TypeVariable) b;
            return va.getGenericDeclaration() == vb.getGenericDeclaration()
                    && va.getName().equals(vb.getName());

        } else {
            // This isn't a type we support. Could be a generic array type, wildcard type, etc.
            return false;
        }
    }
}

3.说明

其实就是实现了一个类似TypeToken或者TypeRefrence的东西。

4.解析使用

同步请求中使用:
写一个请求类继承ParseType:

public class SyncRequest extends ParseType {

    public T syncRequest(String url,Params  params) throws Exception{
        String jsonString = 网络请求代码略...;
        T parse = JSON.parseObject(jsonString,mType);
        return parse;
    }
}

请求+解析:

User user = new SyncRequest().syncRequest(url,params);
NetReslult> data =  new SyncRequest>>(){}.syncRequest(url,params);

看着像不像一个方法解析了所有数据。

你可能感兴趣的:(Gson、Fastjson解析里的Type,如何用一个方法解析所有数据)