简体   繁体   English

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

[英]How to do Custom Serialization using GSON?

I have a case where I would like to use GSON custom serialization feature. 我有一种情况,我想使用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;
   }

}

Now when I do 现在当我做

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);

I get output like this: 我得到这样的输出:

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

But I want it to be : 但我希望它是:

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

How do I achieve this using GSON custom serialization? 如何使用GSON自定义序列化实现此目标?

I have tried this and this . 我已经尝试过这个这个 But did not help much. 但是并没有太大帮助。

This 这个

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

is not valid JSON (you can verify it yourself using an online tool like jsonlint ). 是无效的JSON(您可以使用jsonlint之类的在线工具自己进行验证)。 See details from the JSON specification : 请参阅JSON规范的详细信息:

Definition of an object : 对象的定义

An object is an unordered set of name/value pairs. 对象是名称/值对的无序集合。 An object begins with { (left brace) and ends with } (right brace). 对象以{(左括号)开始,以}(右括号)结束。 Each name is followed by : (colon) and the name/value pairs are separated by , (comma). 每个名称后跟有:(冒号),名称/值对之间以,(逗号)分隔。

Definition of an array : 数组的定义

An array is an ordered collection of values. 数组是值的有序集合。 An array begins with [ (left bracket) and ends with ] (right bracket). 数组以[(左括号)开头,以](右括号)结尾。 Values are separated by , (comma). 值之间以,(逗号)分隔。

Definition of a value : 值的定义

A value can be a string in double quotes, or a number, or true or false or null, or an object or an array. 值可以是带双引号的字符串,也可以是数字,也可以是true或false或null,或者是对象或数组。 These structures can be nested. 这些结构可以嵌套。

Your output defines a JSON array, but the objects in that array aren't properly surrounded with braces. 您的输出定义了一个JSON数组,但是该数组中的对象没有被大括号正确包围。 A correct representation would look like this: 正确的表示应如下所示:

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

Which can be generated with this simple Gson TypeAdapter : 可以使用以下简单的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 method: 测试方法:

@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);
}

And 'relevant' output: 和“相关”输出:

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

First of all you can't get output as ["student":{"name":"sam","rollNumer":1},"student":{"name":"tom","rollNumer":2}] because you are trying to convert object into json not array of object. 首先,您无法以[“ student”:{“ name”:“ sam”,“ rollNumer”:1},“ student”:{“ name”:“ tom”,“ rollNumer”:2}的形式获取输出],因为您尝试将对象转换为json而不是对象数组。

I tried your code and I am getting following output 我尝试了您的代码,并且得到以下输出

{"students":[{"name":"sam","rollNumber":1},{"name":"tom","rollNumber":2}]} {“学生”:[{“名称”:“ sam”,“ rollNumber”:1},{“ name”:“ tom”,“ rollNumber”:2}]}

Here is code : 这是代码:

    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));

You are getting the correct result according to your classes. 根据您的课程,您将获得正确的结果。

You have objects Student that look like this: 您有对象Student看起来像这样:

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

It's simple, an object in JSON is surrounded with {} and contains pairs of property/value... 很简单,JSON中的对象被{}包围,并包含成对的属性/值...

Then, arrays in JSON are surrounded with [] and contains a number of objects/values separated by commas. 然后,JSON中的数组用[]包围,并包含许多用逗号分隔的对象/值。 As you have an array of Student you just have a number of objects like the one above separated by commas and all surrounded by [] . 当您拥有一组Student您将拥有多个对象,例如上面的一个对象,这些对象之间用逗号隔开,并全部用[]包围。

And this is exactly what you have... everything makes sense! 这就是您拥有的一切……一切都说得通!

OK, you want the JSON to contain "student" before each Student object, but what is this string "student" ? OK,您希望JSON在每个Student对象之前包含"student" ,但是此字符串"student"什么? Where does it come from? 它从何而来? In fact there's no such string anywhere in your classes, so how do you want Gson (or whatever library) to include it in the JSON? 实际上,在您的类中的任何地方都没有这样的字符串,那么您如何希望Gson(或任何库)将其包含在JSON中?

If you really need that string, you need to include it somehow in your classes, and the simplest way I come up with is to have a Map instead of an array, like this: 如果确实需要该字符串,则需要以某种方式将其包含在类中,而我想到的最简单的方法是使用Map而不是数组,如下所示:

public Map<String, Student> students;

And then add the students to the map like this: 然后像这样将学生添加到地图中:

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

Note that now you do have the string "student" , associated with a student as the key in the map... 请注意,现在您确实有字符串"student" ,与学生相关联,作为地图中的键...

Now you will have more or less the result you want, but not exactly! 现在,您将或多或少地获得所需的结果,但不完全是! because the whole thing will be surrounded by {} instead of [] , because a Map is an object, not an array... 因为整个事情将被{}而不是[]包围,因为Map是一个对象,而不是数组...

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

I'm afraid the response exactly as you want it is not possible to get (as far as I understand)... 恐怕无法完全获得您所希望的响应(据我所知)...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM