1

我有一个案例,我想使用 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 自定义序列化来实现这一点?

我试过这个这个。但并没有太大帮助。

4

3 回答 3

4

这个

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

不是有效的 JSON(您可以使用jsonlint等在线工具自行验证)。请参阅JSON 规范中的详细信息:

对象的定义

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

数组的定义

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

值的定义

值可以是双引号中的字符串、数字、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}}]}
于 2013-05-09T14:21:12.860 回答
1

首先你不能得到输出 ["student":{"name":"sam","rollNumer":1},"student":{"name":"tom","rollNumer":2} ] 因为您试图将对象转换为 json 而不是对象数组。

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

{"students":[{"name":"sam","rollNumber":1},{"name":"tom","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));
于 2013-05-09T13:06:33.953 回答
1

根据您的课程,您将获得正确的结果。

您有Student如下所示的对象:

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

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

然后,JSON 中的数组被包围[]并包含许多用逗号分隔的对象/值。由于您有一个数组,因此Student您只有许多对象,例如上面用逗号分隔的对象,并且全部由[].

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

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

如果您确实需要该字符串,则需要以某种方式将其包含在您的类中,而我想出的最简单的方法是使用 aMap而不是数组,如下所示:

public Map<String, Student> students;

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

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

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

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

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

恐怕无法得到完全符合您要求的响应(据我所知)...

于 2013-05-09T14:21:45.753 回答