找到你要的答案

Q:GSON custom serializer for an object with a Collection field

Q:gson自定义序列化程序与现场收集的对象

I have the following schema:

public class Student {
    String name;
    List<Integer> sequence;
}

I need the Json of my Student object to be

{
    name : "Bruce"
    sequence : {
         index_0 : 5
         index_1 : 2
         index_2 : 7
         index_3 : 8
    }
}

The documentation doesn't clearly say how to write a serializer for collections.

我有以下模式:

public class Student {
    String name;
    List<Integer> sequence;
}

我需要我的学生对象的JSON是

{
    name : "Bruce"
    sequence : {
         index_0 : 5
         index_1 : 2
         index_2 : 7
         index_3 : 8
    }
}

文件没有明确说如何写一个序列化程序集。

answer1: 回答1:

You could create a TypeAdapter, something like:

public static class StudentAdapter extends TypeAdapter<Student> {
    public void write(JsonWriter writer, Student student)
            throws IOException {
        if (student == null) {
            writer.nullValue();
            return;
        }
        writer.beginObject();

        writer.name("name");
        writer.value(student.name);

        writer.name("sequence");
        writeSequence(writer, student.sequence);

        writer.endObject();
    }

    private void writeSequence(JsonWriter writer, List<Integer> seq)
            throws IOException {
        writer.beginObject();
        for (int i = 0; i < seq.size(); i++) {
            writer.name("index_" + i);
            writer.value(seq.get(i));
        }
        writer.endObject();
    }

    @Override
    public Student read(JsonReader in) throws IOException {
        // This is left blank as an exercise for the reader
        return null;
    }
}

And then register it with

GsonBuilder b = new GsonBuilder();
b.registerTypeAdapter(Student.class, new StudentAdapter());
Gson g = b.create();

If you run this with an example student:

Student s = new Student();
s.name = "John Smith";
s.sequence = ImmutableList.of(1,3,4,7); // This is a guava method
System.out.println(g.toJson(s));

Output:

{"name":"John Smith","sequence":{"index_0":1,"index_1":3,"index_2":4,"index_3":7}}

你可以创建一个typeadapter,像:

public static class StudentAdapter extends TypeAdapter<Student> {
    public void write(JsonWriter writer, Student student)
            throws IOException {
        if (student == null) {
            writer.nullValue();
            return;
        }
        writer.beginObject();

        writer.name("name");
        writer.value(student.name);

        writer.name("sequence");
        writeSequence(writer, student.sequence);

        writer.endObject();
    }

    private void writeSequence(JsonWriter writer, List<Integer> seq)
            throws IOException {
        writer.beginObject();
        for (int i = 0; i < seq.size(); i++) {
            writer.name("index_" + i);
            writer.value(seq.get(i));
        }
        writer.endObject();
    }

    @Override
    public Student read(JsonReader in) throws IOException {
        // This is left blank as an exercise for the reader
        return null;
    }
}

然后注册它

GsonBuilder b = new GsonBuilder();
b.registerTypeAdapter(Student.class, new StudentAdapter());
Gson g = b.create();

如果你运行这个例子学生:

Student s = new Student();
s.name = "John Smith";
s.sequence = ImmutableList.of(1,3,4,7); // This is a guava method
System.out.println(g.toJson(s));

输出:

{"name":"John Smith","sequence":{"index_0":1,"index_1":3,"index_2":4,"index_3":7}}
answer2: 回答2:

GSON supports a custom FieldNamingStrategy:

new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {
    @Override
    public String translateName(java.lang.reflect.Field f) {
        // return a custom field name
    }
});

But this obviously does not cover your case, an easy workaround i can think of would be to make your sequence list transient and have an actual sequence map with the corrected data for GSON:

public class Student {
    String name;
    transient List<Integer> sequenceInternal;
    Map<String, Integer> sequence;
}

and whenever a change occurs on your sequenceInternal object, write the changes through to the sequence map.

gson支持自定义FieldNamingStrategy:

new GsonBuilder().setFieldNamingStrategy(new FieldNamingStrategy() {
    @Override
    public String translateName(java.lang.reflect.Field f) {
        // return a custom field name
    }
});

但这显然不包括你的情况,一个简单的我能想到的解决方法会让你有一个有序列表的瞬态校正数据gson实际序列图:

public class Student {
    String name;
    transient List<Integer> sequenceInternal;
    Map<String, Integer> sequence;
}

和你的sequenceinternal对象发生改变的时候,改变写通过对序列图。

java  json  serialization  collections  gson