使用Gson或者fastjson解析数据,我们的梦想是用一套方法解析所有数据:
public<T> T parse(String jsonStr,Class<T> clazz)
但这只能是想想,比如上面的方法,list类型就没法处理了
解析object和list,肯定得分开俩方法写,想用一个方法的话就得手动传Type。Gson和fastjson之类都有生成Type的辅助类TypeToken 和TypeReference。
TypeToken 和TypeReference都是辅助生成Type的工具类(大概是这样,没仔细研究过),其实这个是可以自己写方法实现的,目标是一个方法来解析所有的数据。参考鸿祥大神的一部分代码和抄袭Gson的部分源码,抽出一个生成Type的类,支持object和list,代码不多两三百行,源码其实我也不懂,只是根据需要抽出来的,
1.获取Type使用如下:
//普通object
Type type = new ParseType<User>() {}.getType();
//列表list
Type type = new ParseType<List<User>>() {}.getType();
//复杂的
Type type = new ParseType<NetReslult<List<User>>>() {}.getType();
//解析
User user = JSON.parseObject(jsonString,type); //fastjson
User user = gson.fromJson(jsonString, type); //gson
NetReslult<List<User>> netResult = JSON.parseObject(jsonString, type);
NetReslult<List<User>> netResult = gson.fromJson(jsonString, type);
ps:注意new出来的是ParseType之类的对象 new ParseType<T>() {},通过泛型这种方式来获取Type类型必须用子类的对象,看清楚了,所有new的ParseType后面都有{}所以生成的是子类的对象。
2.ParseType源码:
public class ParseType<T> {
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> 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<T> extends ParseType<T> {
public T syncRequest(String url,Params params) throws Exception{
String jsonString = 网络请求代码略...;
T parse = JSON.parseObject(jsonString,mType);
return parse;
}
}
请求+解析:
User user = new SyncRequest<User>().syncRequest(url,params);
NetReslult<List<User>> data = new SyncRequest<NetReslult<List<User>>>(){}.syncRequest(url,params);
看着像不像一个方法解析了所有数据。。