JSON基础-java中JSON字符串的转换

一、简单对比

         随着JSON这种数据格式在java编程中的不断使用,需要在JSON对象和普通对象之间进行相互转换,转换的第三方jar也有很多,但是其性能相差比较大。常见的有三种,Jackson 、 JSON-lib、Gson。网上都能下载都jar包以及源代码,有兴趣可以研究一下。
        许多大神对这些包进行了性能比较,总体而言,性能从好到差:Jackson>Gson>Json-lib,Jackson的处理能力差不多要高出其他两个一个数量级以上。这在数据吞吐量极大的情况下是非常可观的。
       具体的测试数据可见:Json第三方jar性能对比
       本文针对常见的Gson和Jackson进行介绍。

二、Gson使用

        2.1基本的转换

public class GsonDemo1 {

	public static void main(String[] args) {
		
		Gson gson = new Gson();
		/**
		 * 基本数据类型转换成JSON字符串
		 */
		String jsonNumber = gson.toJson(100);
		String jsonBoolean = gson.toJson(false);
		String jsonString = gson.toJson("wanwei");
		
		System.out.println(jsonNumber);  //100
		System.out.println(jsonBoolean); //fasle
		System.out.println(jsonString); //"wangwei"
		
		/**
		 * JSON字符串转换成基本数据类型
		 */
		int i= gson.fromJson("100", int.class);    //100         
		double d = gson.fromJson("\"24.45\"", double.class);//24
		String str = gson.fromJson("wangww", String.class);//wangww
		
		System.out.println(i);
		System.out.println(d);
		System.out.println(str);
		
		/**
		 * Task对象转换为JSON字符串
		 */
		Task task = new Task("task001",34,"这是第34号任务!");
		String taskJsonString = gson.toJson(task);
		System.out.println(taskJsonString);  //{"TaskName":"task001","TaskNo":34,"TaskString":"这是第34号任务!"}
		
		
		/**
		 * JSON字符串转换为Task对象
		 */
	   // String taskJson = "{\"TaskName\":\"task001\",\"TaskNo\":34,\"TaskString\":\"这是第34号任务!\"}";  如果采用双引号,里面的""必须转义
		String taskJson = "{'TaskName':'task002','TaskNo':35,'TaskString':'这是第35号任务!'}";//也可以采用单引号
		Task task1 = gson.fromJson(taskJson,Task.class);
		System.out.println(task1.TaskName);
	}
}

/**
 * 
 * Task类
 *
 */
class Task{
		
	public String TaskName;
	public int TaskNo;
	public String TaskString;
	public Task(String taskName, int taskNo, String taskString/*,Date date*/) {
		super();
		this.TaskName = taskName;
		this.TaskNo = taskNo;
		this.TaskString = taskString;
	}
}

       2.2注解的使用

       有一个非常好用的注解@SerializedName,你可以通过反编译工具查看它的源代码,在gson 2.3的时候只有一个value属性,在gson 2.4的时候有两个属性,value和alternate两个属性。alternate可以接受一个String[]数组。
       作用:为了防止Json字符串中的key值和实体类中的属性名在不对应的情况下能够正常转换。
       例如上面的Task类,如果Json字符串写成String taskJson = "{'taskname':'task002'}",那么由于taskname和实体类中的TaskName大小写不对应,造成转换之后为null。 
@SerializedName(value="taskname",alternate={"name","name1"})
	public String TaskName;
	public int TaskNo;
	public String TaskString;
       在上述代码中,Json字符串中不管写成"taskname"、’"name"、"name1"都可以转化为Task对象中TaskName中的值。

       2.3数组和集合的转换

        数组的转换
        
public class GsonDemo2 {

	public static void main(String[] args) {
		
		Gson gson = new Gson();
		String jsonArray = "['task001','task002','task003']";
		String[] str = gson.fromJson(jsonArray, String[].class);
		for (String string : str) {
			System.out.print(string+" ");
		}
	}
}

        集合的转换
       
		List stringList = gson.fromJson(jsonArray, new TypeToken>(){}.getType());
		
		for(String string:stringList){
			System.out.println(string+" ");
		}
       由于TypeToken中的构造方法是protected的,所以需要写成带大括号的。

       2.4 日期格式的转换

		Gson gson = new GsonBuilder()
		        //序列化null
		        .serializeNulls()
		        // 设置日期时间格式,另有2个重载方法
		        // 在序列化和反序化时均生效
		        .setDateFormat("yyyy-MM-dd")
		        // 禁此序列化内部类
		        .disableInnerClassSerialization()
		        //生成不可执行的Json(多了 )]}' 这4个字符)
		        .generateNonExecutableJson()
		        //禁止转义html标签
		        .disableHtmlEscaping()
		        //格式化输出
		        .setPrettyPrinting()
		        .create();
         具体使用方法和其他一样。

         2.5 一些不常用的高级用法

        参见Gson高级用法

三、Jackson使用

         3.1 JSON对象或者集合转换为json字符串

                 /**
		 * Json对象转换成json字符串
		 */
		Task task = new Task("task001",23,"This is the 23th task",new SimpleDateFormat("yyyy-MM-dd").parse("2012-12-21"));
		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(task);
		System.out.println(json);
		
		/**
		 * Java集合转换成json字符串
		 */
		Task task1 = new Task("task001",23,"This is the 23th task",new SimpleDateFormat("yyyy-MM-dd").parse("2012-12-21"));
		List list  = new ArrayList(); 
		list.add(task);
		list.add(task1);
		
		String jsonArray = mapper.writeValueAsString(list);
		System.out.println(jsonArray);

        3.2 JSON字符串转换为JSON对象

       Demo1:反序列化,Date类型传的是一个时间戳
public static void main(String[] args) throws ParseException, IOException {		
                ObjectMapper mapper2 = new ObjectMapper();
		String taskJson = "{\"TaskName\":\"task002\",\"TaskNo\":35,\"TaskString\":\"这是第35号任务!\",\"date\":23232523525}";
		Task task2 = mapper2.readValue(taskJson, Task.class);
		System.out.println(task2.TaskName);	
}


/**
 * 
 * Task类
 *
 */
class Task{
	public String TaskName;
	public Integer TaskNo;
	public String TaskString;
	public Date date;

}
       Demo2:反序列化,Date类型传的是一个String类型字符串
public class JacksonDemo {
	
	public static void main(String[] args) throws ParseException, IOException {
 
		 /**
		  * json字符串转化为java对象  支持从byte[] File InputStream 字符串等数据的JSON反序列化
	     */
		ObjectMapper mapper2 = new ObjectMapper();
		String taskJson = "{\"TaskName\":\"task002\",\"TaskNo\":35,\"TaskString\":\"这是第35号任务!\",\"date\":\"2014-02-19\"}";
		Task task2 = mapper2.readValue(taskJson, Task.class);
		System.out.println(task2.TaskName);	
	}
}


/**
 * 
 * Task类
 *
 */
class Task{
	public String TaskName;
	public Integer TaskNo;
	public String TaskString;
	@JsonDeserialize(using = CustomDateDeserialize.class)
	public Date date;
	
}


/**
 * 也适用于其他类型的反序列化
 *
 *
 */
class CustomDateDeserialize extends JsonDeserializer {  
	  
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  
  
    //private DecimalFormat df = new DecimalFormat("##.00");  //例如反序列化一个double类型对象
    @Override  
    public Date deserialize(JsonParser jp, DeserializationContext ctxt)  
            throws IOException, JsonProcessingException {  
  
        Date date = null;  
        try {  
            date = sdf.parse(jp.getText());  
        } catch (ParseException e) {  
            e.printStackTrace();  
        }  
        return date;  
    }  
} 

Note: 不知道什么原因,当给实体类添加自定义构造函数之后,反序列化就会失败。





你可能感兴趣的:(数据格式)