当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

[Gson八]GsonBuilder序列化和反序列化选项enableComplexMapKeySerialization

发表于: 2014-08-14   作者:bit1129   来源:转载   浏览:
摘要: enableComplexMapKeySerialization配置项的含义  Gson在序列化Map时,默认情况下,是调用Key的toString方法得到它的JSON字符串的Key,对于简单类型和字符串类型,这没有问题,但是对于复杂数据对象,如果对象没有覆写toString方法,那么默认的toString方法将得到这个对象的Hash地址。   GsonBuilder用于

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

 

 

 

 

 

 

 

 

[Gson八]GsonBuilder序列化和反序列化选项enableComplexMapKeySerialization

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
在详细介绍Gson的序列化和反序列化之前,先通过自己在开发过程中遇到的一个问题以及简单的解决方案
本文内容按如下方式组织: 第一部分给出了序列化和反序列化的定义,以及其在通讯协议中所处的位置;
最近公司项目中用到了Json操作,从.NET后台读取数据,通过Json转化在传给“Andiron”端呈现,于是通
原文出处:http://www.ibm.com/developerworks/cn/java/j-lo-serial/ 引言 将 Java 对象序列化为二
windows phone学习也有一段时间了,想要做一个新闻客户端练练手,于是就在网上找看有没有接口之类。
基本概念: 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流
序列化和反序列化我们可能经常会听到,其实通俗一点的解释,序列化就是把一个对象保存到一个文件或数
题目: 背景: 星期六给我班X姐布置了个集合方面的两个简单的题目,虽然布置了自己也没去看,她做的
序列化是将对象状态转换为可保持或传输的形式的过程。序列化的补集是反序列化,后者将流转换为对象
什么叫做对象的序列化?   一个对象产生之后实际上就在内存中开辟了一个存储空间,方便存储信息。
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号