我有一个案例,我想使用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自定义序列化实现此目的?
答案 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}}
我担心你的反应完全不可能(据我所知)......