json将java带泛型的字符串读取。
在json转java的过程中常见 TypeReference<List<String>>(){}作为mapper读取字符串转java类型的参数。该类的构造函数如下。该类由jackson提供。
package com.fasterxml.jackson.core.type; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; //This generic abstract class is used for obtaining full generics type information //by sub-classing; 截取的注释,该类通过子类来获取完整的泛型类型 public abstract class TypeReference<T> implements Comparable<TypeReference<T>> { protected final Type _type; protected TypeReference() { //返回父类类型,如果父类是泛型类,则返回的内容包含泛型,且该泛型是被实际参数传递后的类型 Type superClass = getClass().getGenericSuperclass(); if (superClass instanceof Class<?>) { // sanity check, should never happen throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); } /* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect * it is possible to make it fail? * But let's deal with specific * case when we know an actual use case, and thereby suitable * workarounds for valid case(s) and/or error to throw * on invalid one(s). */ //获取真实的泛型参数(到这已经是父类的泛型参数了),感觉就是直接取出了<>中的内容 _type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; } public Type getType() { return _type; } /** * The only reason we define this method (and require implementation * of <code>Comparable</code>) is to prevent constructing a * reference without type information. */ @Override public int compareTo(TypeReference<T> o) { return 0; } // just need an implementation, not a good one... hence ^^^ }
上面类型在使用时是:TypeReference<List<String>>(){} 其实就是获取了这个类的List<String>这一部分,将其中获取类的代码拿出测试后,
package com.shixun; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; public class fanxing { public static void main(String[] args) { fanxing x = new fanxing(); Class cls = x.getClass(); Method [] methods = cls.getDeclaredMethods(); for(Method m: methods) { System.out.println(m); } System.out.println("验证部分"); B pair = new B(); //因为获取的是父类,所以子类没有传递泛型参数 Double x1 = new Double(1.0); Double x2 = new Double(2.0); System.out.println("是否和Integer一样由缓存"+(x1==x2)); } public static <T> T add(T x,T y){ //输出Object Object return y; } } class Pair<K,V>{ private K k; private V v; public K getK() { return k; } public void setK(K k) { this.k = k; } public V getV() { return v; } public void setV(V v) { this.v = v; } } class B<A, C, V, K> extends Pair<Map<String, Object>,V>{ public B() { super(); Type superClass = getClass().getGenericSuperclass(); Type [] type = ((ParameterizedType) superClass).getActualTypeArguments(); for(Type t: type) { System.out.print(t); } System.out.println(); System.out.println(((ParameterizedType) superClass).getActualTypeArguments()[0]); } }
输出的结果如下
public static void com.shixun.fanxing.main(java.lang.String[]) public static java.lang.Object com.shixun.fanxing.add(java.lang.Object,java.lang.Object) 验证部分 java.util.Map<java.lang.String, java.lang.Object>V //其中一个类型是V 上面是获取父类的类型,下面是获取第一个 java.util.Map<java.lang.String, java.lang.Object> 是否和Integer一样由缓存false
如果形参是String,则取得Java.lang.String。
/////////////////////////////////////////////////////
在json转java类型的时候主要用public <T> T readValue(String content, Class<T> valueType)或者public <T> T readValue(String content, JavaType valueType)或者public <T> T readValue(String content, TypeReference valueTypeRef)在这样三个重载的方法中,第一个方法中放入要转成的对应对象的Class对象就行。但是对于含有泛型的类型例如:List<String>或者HashMap<String, Bean>对于第一个方法来说就只能获取List.Class或者HashMap.Class,其中的泛型类型则会丢失,能不能用呢,测试后发现是可以用的(个人认为会用Object来作为所有数据的类型,如果这时候在赋值给List<String>估计会进行类型的强制转换),所有才有了之后的两个重载的方法,因为后面的方法保存了泛型类型的信息,所以速度比较快也更精确。后面两种重载方法的使用方法如下。
CollectionType javaType = mapper.getTypeFactory() .constructCollectionType(List.class, Person.class); List<Person> personList = mapper.readValue(jsonInString, javaType); List<Person> personList = mapper.readValue(jsonInString, new TypeReference<List<Person>>(){}); MapType javaType = mapper.getTypeFactory().constructMapType(HashMap.class,String.class, Person.class); Map<String, Person> personMap = mapper.readValue(jsonInString, javaType); Map<String, Person> personMap = mapper.readValue(jsonInString, new TypeReference<Map<String, Person>>(){});
并且后面两种方法的接受的泛型类中的泛型参数填什么都可以,(第三个是的,第二个没试)就是TypeReference中的泛型参数一定要正确,但接收的Map<String, Person>即便写成Map<Integer, Integer>也可以接收(估计这时候会涉及到类型的强制转换)。因为源码点进入后如下
@SuppressWarnings({ "unchecked", "rawtypes" }) public <T> T readValue(String content, TypeReference valueTypeRef) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef)); } @SuppressWarnings("unchecked") public <T> T readValue(String content, JavaType valueType) throws IOException, JsonParseException, JsonMappingException { return (T) _readMapAndClose(_jsonFactory.createParser(content), valueType); }
整个过程T都没有被赋值,要想给T赋值如下即可
Map<String, Object> temp = mapper.<Map<String, Object>>readValue(new File("newPerson.json"), new TypeReference<Map<String, Object>>(){});
////////////////////////////////////////////////////////////////////
常用方法
mapper.writeValue(new File("newPerson.json"), personDataMap); 将对象写如流中
mapper.writeValueAsString(value),将对象转换为String并返回。
下面是json到对象的转换
public <T> T readValue(String content, Class<T> valueType)
public <T> T readValue(String content, JavaType valueType)
public <T> T readValue(String content, TypeReference valueTypeRef)
下面是从Web服务器到页面
未整理杂项,搜索mapper https://www.cnblogs.com/ant-xu/p/11485270.html