如何使用GSON进行自定义序列化?

时间:2013-05-09 12:43:11

标签: java json gson

我有一个案例,我想使用GSON自定义序列化功能。

class Student{
   public String name;
   public int rollNumber;

   public Student(String name, int rollNumber){
        this.name = name;
        this.rollNumber = rollNumber;
   }

   public int getRollNumber(){
       return this.rollNumber;
   }

   public String getName(){
       return this.name;
   }


}
class School{

    public Student[] students;

    public School(Student[] students){
          this.students = students;
    }


   public Students[] getStudents(){
       return this.students;
   }

}

现在我做的时候

private static final Gson GSON = new GsonBuilder().disableHtmlEscaping().create();

Student[] students = new Student[2];

students[0] = new Student("sam", 1);

students[1] = new Student("tom", 2);

School school = new School(students);

GSON.toJson(school);

我得到这样的输出:

[{"name":"sam","rollNumer":1},{"name":"tom","rollNumer":2}]

但我希望它是:

["student":{"name":"sam","rollNumer":1},"student":{"name":"tom","rollNumer":2}]

如何使用GSON自定义序列化实现此目的?

我尝试过thisthis。但没多大帮助。

3 个答案:

答案 0 :(得分:4)

["student":{"name":"sam","rollNumer":1},"student":{"name":"tom","rollNumer":2}]

是无效的JSON(您可以使用jsonlint等在线工具自行验证。请参阅JSON specification

中的详细信息

对象的定义

  

对象是一组无序的名称/值对。对象以{(左括号)开头,以}结尾(右大括号)。每个名称后跟:(冒号),名称/值对用(逗号)分隔。

数组的定义

  

数组是有序的值集合。数组以[(左括号)开头,以]结尾(右括号)。值以(逗号)分隔。

值的定义

  

值可以是双引号或数字,或true或false或null,或对象或数组的字符串。这些结构可以嵌套。

您的输出定义了一个JSON数组,但该数组中的对象没有用大括号正确包围。正确的表示形式如下:

[{"student":{"name":"sam","rollNumer":1}}, {"student":{"name":"tom","rollNumer":2}}]

可以使用这个简单的Gson生成TypeAdapter

class StudentAdapter extends TypeAdapter<Student> {

    @Override
    public void write(final JsonWriter writer, final Student student)
            throws IOException {
        if (student == null) {
            writer.nullValue();
            return;
        }

        writer.beginObject();
        writer.name("student");
        writer.beginObject();
        writer.name("name");
        writer.value(student.getName());
        writer.name("rollNumber");
        writer.value(student.getRollNumber());
        writer.endObject();
        writer.endObject();
    }

    @Override
    public Student read(final JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
            reader.nextNull();
            return null;
        }

        final Student student = new Student();
        reader.beginObject();
        reader.nextName(); // discard the 'student' wrapper property
        reader.beginObject();
        while (reader.hasNext()) {
            final String attrName = reader.nextName();
            if ("name".equals(attrName)) {
                student.setName(reader.nextString());
            } else if ("rollNumber".equals(attrName)) {
                student.setRollNumber(reader.nextInt());
            }
        }
        reader.endObject();
        reader.endObject();

        return student;
    }
}

测试方法:

@Test
public void testWriteSchoolsAsJSONWithGsonAndCustomOutput()
        throws Exception {
    final Gson gson = new GsonBuilder().registerTypeAdapter(Student.class,
            new StudentAdapter()).create();

    Student[] students = new Student[2];
    students[0] = new Student("sam", 1);
    students[1] = new Student("tom", 2);

    School school = new School(students);

    final String outputJson = gson.toJson(school);
    System.out.println(outputJson);

    school = gson.fromJson(outputJson, School.class);
    System.out.println(school);
}

和'相关'输出:

{"students":[{"student":{"name":"sam","rollNumber":1}},{"student":{"name":"tom","rollNumber":2}}]}

答案 1 :(得分:1)

首先,你无法输出[“学生”:{“name”:“sam”,“rollNumer”:1},“student”:{“name”:“tom”,“rollNumer” :2}]因为你试图将对象转换为json而不是对象数组。

我尝试了你的代码,我得到了以下输出

{ “学生”:[{ “名称”: “SAM”, “rollNumber”:1},{ “名称”: “汤姆”, “rollNumber”:2}]}

这是代码:

    Student[] students = new Student[2];

    students[0] = new Student("sam", 1);

    students[1] = new Student("tom", 2);

    School school = new School(students);

    Gson gson = new GsonBuilder().disableHtmlEscaping().create();

    System.out.println(gson.toJson(school));

答案 2 :(得分:1)

您根据班级得到了正确的结果。

您的对象Student如下所示:

{"name":"sam", "rollNumer":1}

很简单,JSON中的一个对象被{}包围,并包含一对属性/值......

然后,JSON中的数组被[]包围,并包含许多以逗号分隔的对象/值。由于你有一个Student数组,你只有许多对象,例如上面用逗号分隔的对象,所有对象都被[]包围。

这正是你所拥有的......一切都有意义!

好的,您希望JSON在每个"student"对象之前包含Student,但这个字符串"student"是什么?它从何而来?实际上你的类中没有这样的字符串,所以你想如何将Gson(或其他库)包含在JSON中?

如果你真的需要那个字符串,你需要在你的课程中以某种方式包含它,而我提出的最简单的方法是使用Map而不是数组,如下所示:

public Map<String, Student> students;

然后将学生添加到地图中:

Student student = new Student("sam", 1);
students.put("student", student);
//add other students...

请注意,现在您确实拥有与学生相关联的字符串"student"作为地图中的关键字...

现在你或多或少会得到你想要的结果,但不完全是!因为整个事物将被{}而不是[]包围,因为Map是一个对象,而不是一个数组......

{"student":{"name":"sam","rollNumer":1}},{"student":{"name":"tom","rollNumer":2}}

我担心你的反应完全不可能(据我所知)......