enableComplexMapKeySerialization配置项的含义
Gson在序列化Map时,默认情况下,是调用Key的toString方法得到它的JSON字符串的Key,对于简单类型和字符串类型,这没有问题,但是对于复杂数据对象,如果对象没有覆写toString方法,那么默认的toString方法将得到这个对象的Hash地址。
GsonBuilder用于为创建Gson对象设置配置选项,这些选项可以覆盖通过Gson gson = new Gson()创建的Gson对象,例如下面的例子代码:
不启用enableComplexMapKeySerialization并且不启动类型适配器(PointTypeAdapter)
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public class Test {
public static void main(String[]args) {
Map<Point, String> map = new HashMap<Point, String>();
Point p1 = new Point();
p1.setX(10);
p1.setY(10);
map.put(p1, "Ten");
Point p2 = new Point();
p2.setX(20);
p2.setY(20);
map.put(p2, "Twenty");
Gson gson = new GsonBuilder().create();
String str = gson.toJson(map);
System.out.println(str);//{"test1.Point@5ba5ba75":"Ten","test1.Point@5d748654":"Twenty"}
Type type = new TypeToken<Map<Point,String>>(){}.getType();
map = gson.fromJson(str, type);//java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
}
}
代码输出 {"Point@6f92c766":"Twenty","Point@6406c7e":"Ten"},可见Key转换成字符串时,使用的Key.toString()方法(这里的Key是Point类型),这样转换结果基本是无法接受的,因为序列化出来的JSON串无法反序列化原来的Map集合。在上面的反序列化时,抛出异常因为Gson因为Point@6f92c766只是一个简单的字符串,无法转型为Point。
启用enableComplexMapKeySerialization配置项,但是不启用类型适配器
如果仅仅启用enableComplexMapKeySerialization配置项,但是不为Point类自定义类型适配器,那么这个Map将被序列化为JSON数组,数组的每个元素也是一个数组,这个数组的长度为2,第一个值为Key转换得到的JSON对象字符串,第二个值是Value对应的JSON字符串。如下代码所示:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
public class Test {
public static void main(String[] args) {
Map<Point, String> map = new HashMap<Point, String>();
Point p1 = new Point();
p1.setX(10);
p1.setY(10);
map.put(p1, "Ten");
Point p2 = new Point();
p2.setX(20);
p2.setY(20);
map.put(p2, "Twenty");
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.enableComplexMapKeySerialization();
Gson gson = gsonBuilder.create();
String str = gson.toJson(map);
System.out.println(str); //[[{"x":10,"y":10},"Ten"],[{"x":20,"y":20},"Twenty"]]
Type type = new TypeToken<Map<Point, String>>(){}.getType();
map = gson.fromJson(str, type); //转换成功
}
}
启用enableComplexMapKeySerialization配置项,并且启用类型适配器
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
class PointTypeAdapter extends TypeAdapter<Point> {
@Override
public void write(JsonWriter out, Point value) throws IOException {
if (value == null) {
out.nullValue();
} else {
out.value("(" + value.getX() + "," + value.getY() + ")");
}
}
@Override
public Point read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
return null;
} else {
String str = in.nextString();
str = str.substring(1, str.length() - 1); //根据writer的格式,解析字符串
String[] pair = str.split(",");
Point p = new Point();
p.setX(Integer.parseInt(pair[0]));
p.setY(Integer.parseInt(pair[1]));
return p;
}
}
}
public class Test {
public static void main(String[] args) {
Map<Point, String> map = new HashMap<Point, String>();
Point p1 = new Point();
p1.setX(10);
p1.setY(10);
map.put(p1, "Ten");
Point p2 = new Point();
p2.setX(20);
p2.setY(20);
map.put(p2, "Twenty");
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().registerTypeAdapter(Point.class, new PointTypeAdapter()).create();
String str = gson.toJson(map);
System.out.println(str); //{"(10,10)":"Ten","(20,20)":"Twenty"}
Type type = new TypeToken<Map<Point, String>>() {
}.getType();
map = gson.fromJson(str, type); //转换成功
}
}
启用类型适配器,但不启用enableComplexMapKeySerialization
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
class Point {
private int x;
private int y;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
class PointTypeAdapter extends TypeAdapter<Point> {
@Override
public void write(JsonWriter out, Point value) throws IOException {
if (value == null) {
out.nullValue();
} else {
out.value("(" + value.getX() + "," + value.getY() + ")");
}
}
@Override
public Point read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
return null;
} else {
String str = in.nextString();
str = str.substring(1, str.length() - 1); //根据writer的格式,解析字符串
String[] pair = str.split(",");
Point p = new Point();
p.setX(Integer.parseInt(pair[0]));
p.setY(Integer.parseInt(pair[1]));
return p;
}
}
}
public class Test {
public static void main(String[] args) {
Map<Point, String> map = new HashMap<Point, String>();
Point p1 = new Point();
p1.setX(10);
p1.setY(10);
map.put(p1, "Ten");
Point p2 = new Point();
p2.setX(20);
p2.setY(20);
map.put(p2, "Twenty");
Gson gson = new GsonBuilder().registerTypeAdapter(Point.class, new PointTypeAdapter()).create();
String str = gson.toJson(map);
System.out.println(str); //{"Point@e0cc23":"Twenty","Point@76ab2f":"Ten"}
Type type = new TypeToken<Map<Point, String>>() {
}.getType();
map = gson.fromJson(str, type); //转换成功
}
}
上面的代码如果仅仅注册PointTypeAdapter而不调用enableComplexMapKeySerialization,序列化的结果仍然是{"Point@e0cc23":"Twenty","Point@76ab2f":"Ten"}
总结
1.如果在序列化Map类型的对象时,如果Key是复杂数据类型(不是基本数据类型或者String,即自定义POJO),此时就要使用enableComplexMapKeySerialization配置选项,否则Gson默认是以Key.toString()作为JSON字符串对应的Key
2.在实际中,麻烦的是根据JSON字符串的结构定义对应的POJO,如果JSON串中key是JSON对象格式,可以考虑使用使用Map,并且把Key定义为复杂类型,然后同时启用enableComplexMapKeySerialization选项和注册TypeAdapter
分享到:
相关推荐
fastjson、gson、jackson序列化和反序列化所用json文件
Gson解析之自定义序列化和反序列化的代码例子,但后端对同一个字段给的数据类型与文档不一致时的处理
fastJosn Gson Jackson 序列化和反序列化所需要的jar,已经全部验证过,请放心使用咯
实现了通过gson对enum的自定义转化过程,不需要预先定义enmu,并且不需要修改gson源码,在框架顶层处理基本可以达到对enum的抽象管理。
Gson 中解决 json 反序列化时相同属性对应不同类型的值的问题(代码),对应文章链接:https://blog.csdn.net/ZiFung_Yip/article/details/89143255
protostuff fastjson gson 高性能序列化jar包
1.3 数组和List的序列化/反序列化 1.3.1 数组的序列化/反序列化 1.3.2 List集合的序列化/反序列化 1.4 Set和Map的序列化/反序列化 1.4.1 Set集合的序列化/反序列化 1.4.2 Map集合的序列化/反序列化 1.5 Map的value为...
集成多枚举类型统一序列化/反序列化处理,再也不用创建多个Adapter了 http://blog.csdn.net/atm008/article/details/51733849
主要讲述Json序列化与反序列化,主要使用Gson、FastJson、Jackson实现
gson-2.0.1.jar-Json解析工具,序列化反序列化,实体类互转Json,免费jar包
Gson里最重要的对象有2个Gson 和 GsonBuilder Gson有2个最基本的方法 1) toJson() – 转换java 对象到JSON 2) fromJson() – 转换JSON到java对象 下面是几个小例子 1. toJson() example Java 代码 收藏代码...
Gson jackson fastjson LoganSquare 使用demo Gson jackson fastjson LoganSquare 使用demo
实现配置化方式,提供多种序列化方式,可以在获取链接的时候使用池,提供了gson实现对象序列化和反序列化,方便直接存取
本资源Java中常用的Json序列化jar包,包括Google的gson.jar序列化包和常用的Json序列化包,亲测可用。 版本分别为:gson-2.8.2.jar和json-20170516.jar
Gson反序列化原理 原理简述 gson反序列化主要分为两个过程: 根据TypeToken创建出对象 根据json字符串解析数据,对对象属性赋值 对象的创建 ConstructorConstructor.get 先尝试获取无参构造函数 失败则尝试...
gson序列化,反序列化工具包,用来做工具报表使用,
各种序列化工具类,包括Gson, Jackson, FastJson, ProtoBuf以及proto.exe,希望大家喜欢
Android基于Gson序列化和反序列化,用于存储对象到xml和从xml中解析对象
目标提供简单的toJson()和fromJson()方法将Java对象转换为JSON,反之亦然允许将已有的不可修改的对象与JSON相互转换Java泛型的广泛支持允许对象的自定义表示支持任意复杂的对象(具有深层继承层次结构和泛型类型的...
GSON是Google开发并开源的一个Java的JSON转换库,这里我们将来讲解GSON实现Java对象的JSON序列化与反序列化的实例教程,需要的朋友可以参考下