java使用Gson进行json字符串反序列化转map对象时,int变为double的解决办法

java处理json字符串与java对象的互转,google家的Gson是个很好的工具。不过使用中也遇到了一些坑(有的其实更像是惊喜),与大家分享下。

一、json字符串反序列化转map对象时,int变为double的解决办法。

二、json字符串中格式时间字符串与Date对象的直接转换。

三、字符串与枚举的直接转换(自带此功能)。

Gson默认的坑

问题:使用Gsonjson字符串转为map时,原来的int类型反序列化后成为double类型。

Json字符串:

"{\"lngnum\":12,\"dbnum\":12.34,\"datetime\":\"2014-12-23 12:09:21\",\"date\":\"2014-12-23\",
\"next\":{\"lngnum\":12,\"dbnum\":12.34,\"datetime\":\"2014-12-23 12:09:21\",\"date\":\"2014-12-23\"}}";

实现方式:

/**
 * 使用默认的gson对象进行反序列化
 *
 * @param json
 * @param typeToken
 * @return
 */
public static <T> T fromJsonDefault(String json, TypeToken<T> typeToken) {
Gson gson = new Gson();
return gson.fromJson(json, typeToken.getType());
}

转化结果:

lngnum-12.0-Double//整型变为了浮点类型
dbnum-12.34-Double
datetime-2014-12-23 12:09:21-String
date-2014-12-23-String
====================
next-Map start
lngnum-12.0-Double//整型变为了浮点类型
dbnum-12.34-Double
datetime-2014-12-23 12:09:21-String
date-2014-12-23-String
next-Map end
====================

方法一:重新实现TypeAdapter

实现方式:

/**
 * json字符串转list或者map
 *
 * @param json
 * @param typeToken
 * @return
 */
public static <T> T fromJson(String json, TypeToken<T> typeToken) {
Gson gson = new GsonBuilder()
/**
 * 重写map的反序列化
 */
.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
}.getType(), new MapTypeAdapter()).create();
//MapTypeAdapter是继承了TypeAdapter类,并单独处理Map类型的反序列化。注意:目前只绑定了Map类型,其子类(HashMap)的处理没有变化。具体代码见本文最后或GitHub(发布后会给出地址)。
return gson.fromJson(json, typeToken.getType());
}

转化结果:

lngnum-12-Long//看!它动了
dbnum-12.34-Double
datetime-2014-12-23 12:09:21-String
date-2014-12-23-String
====================
next-Map start
lngnum-12-Long//看!它动了
dbnum-12.34-Double
datetime-2014-12-23 12:09:21-String
date-2014-12-23-String
next-Map end
====================

方法二:使用java bean接收 && 意外惊喜,格式化时间字符串与Date对象

实现方式:

/**
 * json字符串转bean对象
 *
 * @param json
 * @param cls
 * @return
 */
public static <T> T fromJson(String json, Class<T> cls) {
Gson gson = new GsonBuilder().setDateFormat(DATEFORMAT_default)
.create();
return gson.fromJson(json, cls);
}

/**
 * java bean定义
 *
 * @author Administrator
 *
 */
public static class TestBean {
private Integer lngnum;//指定类型,省好多事
private Double dbnum;
private Date datetime;//指定类型,省好多事
private Date date;//指定类型,省好多事
private TestBean next;//指定类型,省好多事
public Integer getLngnum() {
return lngnum;
}
public void setLngnum(Integer lngnum) {
this.lngnum = lngnum;
}
public Double getDbnum() {
return dbnum;
}
public void setDbnum(Double dbnum) {
this.dbnum = dbnum;
}
public Date getDatetime() {
return datetime;
}
public void setDatetime(Date datetime) {
this.datetime = datetime;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public TestBean getNext() {
return next;
}
public void setNext(TestBean next) {
this.next = next;
}
}

转化结果:

{
  "lngnum": 12,//我又回来了
  "dbnum": 12.34,
  "datetime": "2014-12-23 12:09:21",//我从string到date,又从date到string。
  "date": "2014-12-23 00:00:00",//楼上说得对!
  "next": {
    "lngnum": 12,
    "dbnum": 12.34,
    "datetime": "2014-12-23 12:09:21",
    "date": "2014-12-23 00:00:00"
  }
}

本文源代码

package com.ldt.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

/**
 * 
 * @author Administrator
 *
 */
public class GsonUtil {

	/**
	 * 实现格式化的时间字符串转时间对象
	 */
	private static final String DATEFORMAT_default = "yyyy-MM-dd HH:mm:ss";

	/**
	 * 使用默认的gson对象进行反序列化
	 * 
	 * @param json
	 * @param typeToken
	 * @return
	 */
	public static <T> T fromJsonDefault(String json, TypeToken<T> typeToken) {
		Gson gson = new Gson();
		return gson.fromJson(json, typeToken.getType());
	}

	/**
	 * json字符串转list或者map
	 * 
	 * @param json
	 * @param typeToken
	 * @return
	 */
	public static <T> T fromJson(String json, TypeToken<T> typeToken) {

		Gson gson = new GsonBuilder()
		/**
		 * 重写map的反序列化
		 */
		.registerTypeAdapter(new TypeToken<Map<String, Object>>() {
		}.getType(), new MapTypeAdapter()).create();

		return gson.fromJson(json, typeToken.getType());

	}

	/**
	 * json字符串转bean对象
	 * 
	 * @param json
	 * @param cls
	 * @return
	 */
	public static <T> T fromJson(String json, Class<T> cls) {

		Gson gson = new GsonBuilder().setDateFormat(DATEFORMAT_default)
				.create();

		return gson.fromJson(json, cls);

	}

	/**
	 * 对象转json
	 * 
	 * @param obj
	 * @param format
	 * @return
	 */
	public static String toJson(Object obj, boolean format) {

		GsonBuilder gsonBuilder = new GsonBuilder();
		/**
		 * 设置默认时间格式
		 */
		gsonBuilder.setDateFormat(DATEFORMAT_default);

		/**
		 * 添加格式化设置
		 */
		if (format) {
			gsonBuilder.setPrettyPrinting();
		}

		Gson gson = gsonBuilder.create();

		return gson.toJson(obj);
	}

	public static class MapTypeAdapter extends TypeAdapter<Object> {

		@Override
		public Object read(JsonReader in) throws IOException {
			JsonToken token = in.peek();
			switch (token) {
			case BEGIN_ARRAY:
				List<Object> list = new ArrayList<Object>();
				in.beginArray();
				while (in.hasNext()) {
					list.add(read(in));
				}
				in.endArray();
				return list;

			case BEGIN_OBJECT:
				Map<String, Object> map = new LinkedTreeMap<String, Object>();
				in.beginObject();
				while (in.hasNext()) {
					map.put(in.nextName(), read(in));
				}
				in.endObject();
				return map;

			case STRING:
				return in.nextString();

			case NUMBER:
				/**
				 * 改写数字的处理逻辑,将数字值分为整型与浮点型。
				 */
				double dbNum = in.nextDouble();

				// 数字超过long的最大值,返回浮点类型
				if (dbNum > Long.MAX_VALUE) {
					return dbNum;
				}

				// 判断数字是否为整数值
				long lngNum = (long) dbNum;
				if (dbNum == lngNum) {
					return lngNum;
				} else {
					return dbNum;
				}

			case BOOLEAN:
				return in.nextBoolean();

			case NULL:
				in.nextNull();
				return null;

			default:
				throw new IllegalStateException();
			}
		}

		@Override
		public void write(JsonWriter out, Object value) throws IOException {
			// 序列化无需实现
		}

	}

}

package com.ldt.utils;

import java.sql.Date;
import java.util.Map;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import com.google.gson.reflect.TypeToken;

public class GsonUtilTest {

 private String json;

 @Before
 public void init_data() {
 json = "{\"lngnum\":12,\"dbnum\":12.34,\"datetime\":\"2014-12-23 12:09:21\",\"date\":\"2014-12-23\",\"next\":{\"lngnum\":12,\"dbnum\":12.34,\"datetime\":\"2014-12-23 12:09:21\",\"date\":\"2014-12-23\"}}";
 }

 @Test
 public void test001fromJsonDefault() {
 Map<String, Object> map = GsonUtil.fromJsonDefault(json,
 new TypeToken<Map<String, Object>>() {
 });
 System.out.println("test001fromJsonDefault-结果展示");
 showMap(map);
 }

 @Test
 public void test002fromJson() {
 Map<String, Object> map = GsonUtil.fromJson(json,
 new TypeToken<Map<String, Object>>() {
 });
 System.out.println("test001fromJsonDefault-结果展示");
 showMap(map);
 }

 @Test
 public void test003fromJson() {
 TestBean bean = GsonUtil.fromJson(json, TestBean.class);
 System.out.println("test001fromJsonDefault-结果展示");
 System.out.println(GsonUtil.toJson(bean, true));
 }

 /**
 * java bean定义
 * 
 * @author Administrator
 *
 */
 public static class TestBean {
 private Integer lngnum;
 private Double dbnum;
 private Date datetime;
 private Date date;
 private TestBean next;

 public Integer getLngnum() {
 return lngnum;
 }

 public void setLngnum(Integer lngnum) {
 this.lngnum = lngnum;
 }

 public Double getDbnum() {
 return dbnum;
 }

 public void setDbnum(Double dbnum) {
 this.dbnum = dbnum;
 }

 public Date getDatetime() {
 return datetime;
 }

 public void setDatetime(Date datetime) {
 this.datetime = datetime;
 }

 public Date getDate() {
 return date;
 }

 public void setDate(Date date) {
 this.date = date;
 }

 public TestBean getNext() {
 return next;
 }

 public void setNext(TestBean next) {
 this.next = next;
 }

 }

 @SuppressWarnings("unchecked")
 private void showMap(Map<String, Object> map) {
 if (map == null) {
 return;
 }

 Set<String> keySet = map.keySet();
 Object value = null;
 for (String key : keySet) {
 value = map.get(key);

 if (value instanceof Map) {
 System.out.println("====================");
 System.out.println(key + "-Map start");
 showMap((Map<String, Object>) value);
 System.out.println(key + "-Map end");
 System.out.println("====================");
 } else {
 System.out.println(key
 + "-"
 + value
 + "-"
 + (value == null ? "NULL" : value.getClass()
 .getSimpleName()));
 }

 }

 }
}

© 2016 – 2017, 德涛. 版权所有.

发表评论

电子邮件地址不会被公开。 必填项已用*标注