Java基础之《jackson转换json、获取泛型Type》

1、json字符串转对象,不带实体类

//用法示例
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(requestStr); //获得根节点
JsonNode txnType = rootNode.get("txnType"); //获得某个json字段
String result = txnType.asText(); //获得它的值

2、json字符串转对象,带实体类的转换

//用法示例
ObjectMapper objectMapper = new ObjectMapper();
AccountBean acc = objectMapper.readValue(json, AccountBean.class);

3、对象转json字符串

//用法示例
ObjectMapper objectMapper = new ObjectMapper();
String result = objectMapper.writeValueAsString(object);

注:writeValueAsString可以转换map、list等集合,实体类

4、json字符串转对象,高级用法一, JavaType
UserBean.java

package test;

public class UserBean {

	String name;
	String password;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}

}

Test.java

package test;

import java.util.List;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Test {
	
	public static void main(String[] args) {
		//使用JavaType
		String constent = "[{\"name\":\"张三\",\"password\":\"123\"},{\"name\":\"李四\",\"password\":\"456\"}]";
		ObjectMapper mapper = new ObjectMapper();
		JavaType javaType = mapper.getTypeFactory().constructCollectionType(List.class, UserBean.class);
		try {
			List<UserBean> lists = mapper.readValue(constent, javaType);
			System.out.println(lists.get(0).getName());
			System.out.println(lists.get(0).getPassword());
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

JavaType的作用:JavaType对象对应着一个java类型,用于寻找对应的反序列化器
参考jackson代码,传入一个上下文,一个工厂,一个JavaType

public JsonDeserializer<Object> findValueDeserializer(DeserializationContext ctxt, DeserializerFactory factory, JavaType propertyType)
    throws JsonMappingException
  {
    JsonDeserializer<Object> deser = _findCachedDeserializer(propertyType); //从缓存中寻找
    if (deser != null) {
      return deser;
    }
    deser = _createAndCacheValueDeserializer(ctxt, factory, propertyType); //创建新的
    if (deser == null) {
      deser = _handleUnknownValueDeserializer(propertyType); //处理未知类型
    }
    return deser;
  }

5、json字符串转对象,高级用法二,TypeReference
json数组转成list

try {
	String json = "[{\"name\":\"张三\",\"password\":\"123\"},{\"name\":\"李四\",\"password\":\"456\"}]";
	List<UserBean> userBeanList = mapper.readValue(json, new TypeReference<List<UserBean>>() {});
	String userName = userBeanList.get(0).getName();
	System.out.println(userName);
} catch (Exception e1) {
	// TODO Auto-generated catch block
	e1.printStackTrace();
}

参考jackson代码

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内部,会获得T的这个泛型类型
写一个例子程序Test.java:

try {
	//生成一个匿名内部类,是TypeReference抽象类的子类
	TypeReference ttt = new TypeReference<List<UserBean>>() {};
	//获得当前匿名类的类类型
	Class clazz = ttt.getClass();
	System.out.println("1: " + clazz);
	
	//获得此匿名类父类的Type类型,即TypeReference<List<UserBean>>的Type类型
	//Type是Java编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型
	//实际上Type接口只是一个标记,Class类实现了Type接口
	Type superClass = ttt.getClass().getGenericSuperclass();
	System.out.println("2: " + superClass);
	
	//获得ParameterizedType参数化类型,即泛型
	ParameterizedType p = (ParameterizedType)superClass;
	System.out.println("3: " + p);
	
	//getActualTypeArguments获取参数化类型的数组,泛型可能有多个
	Type type = p.getActualTypeArguments()[0];
	System.out.println("4: " + type);
	
} catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

执行结果:

1: class test.Test$1
2: com.fasterxml.jackson.core.type.TypeReference<java.util.List<com.ips.core.pbcs.biz.gateway.UserBean>>
3: com.fasterxml.jackson.core.type.TypeReference<java.util.List<com.ips.core.pbcs.biz.gateway.UserBean>>
4: java.util.List<com.ips.core.pbcs.biz.gateway.UserBean>

 加断点可以看到,保存的信息:

参考资料:
https://blog.csdn.net/liang5630/article/details/40185591
https://www.jianshu.com/p/0851fe6f7d62
 

猜你喜欢

转载自blog.csdn.net/csj50/article/details/108849717