gson 自定义特定的序列化的方式

有一个 Student 类,包含了 id 和 name 两个属性,使用 SpringMVC 和 gson 整合,默认 gson 将该实体会序列化为:

{
    "id" : 1,
    "name" : "StuName"
}

目前希望将 Student 序列化为:

{
    "Type" : "Student",
    "Property": {
        "id" : 1,
        "name" : "StuName"
    }
}

请问大家该如何做呢?(gson 版本为 2.8.0,使用 TypeAdapter 我一直得不到想要的效果。使用 Jackson 的时候,可以直接定义一个 JsonSerializer 并将其使用 @JsonSerialize(using = xxx.class) 注解来自定义序列化的格式,不知道在 gson 中有没有提供的方式)

阅读 7.4k
2 个回答

用:JsonSerializer/JsonDeserializer

    public static class StudentJsonSerializer implements JsonSerializer<Student> {
        @Override
        public JsonElement serialize(Student src, Type typeOfSrc, JsonSerializationContext context) {
            final JsonObject propEle = new JsonObject();
            propEle.addProperty("id", src.getId());
            propEle.addProperty("name", src.getName());

            final JsonObject root = new JsonObject();
            root.addProperty("Type", "Student");
            root.add("Property", propEle);

            return root;
        }
    }
    
    public static class StudentJsonDeserializer implements JsonDeserializer<Student> {
        public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            final JsonObject root = json.getAsJsonObject();
            JsonObject propEle = root.getAsJsonObject("Property");

            Student student = new Student();
            student.setId(propEle.get("id").getAsInt());
            student.setName(propEle.get("name").getAsString());
            return student;
        }
    }
    
    @Test
    public void test_1010000010436869() {
        Gson gson = new GsonBuilder().registerTypeAdapter(Student.class, new StudentJsonSerializer())
                .registerTypeAdapter(Student.class, new StudentJsonDeserializer()).create();
        Student student = new Student();
        student.setId(1);
        student.setName("StuName");
        String json = gson.toJson(student);
        System.out.println(json);

        Student student2 = gson.fromJson(json, Student.class);
        System.out.println(student2);
    }

通过继承 GsonHttpMessageConverter 并覆写 writeInternal 方法达到了想要的效果,但不知道有没有更加优雅的方法。

public class MyGsonHttpMessageConverter extends GsonHttpMessageConverter {

    @Override
    protected void writeInternal(Object o, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        if (o instanceof Student) {

            Student s = (Student) o;

            JsonObject stuObj = new JsonObject();
            stuObj.addProperty("id", s.getId());
            stuObj.addProperty("name", s.getName());

            JsonObject entity = new JsonObject();
            entity.addProperty("Type", "Student");
            entity.add("property", stuObj);

            try (OutputStreamWriter writer = new OutputStreamWriter(outputMessage.getBody(), DEFAULT_CHARSET)) {

                Gson gson = super.getGson();
                gson.toJson(entity, writer);

            } catch (JsonIOException ex) {
                throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
            }

        } else {
            super.writeInternal(o, type, outputMessage);
        }
    }

}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题