Jackson自定义序列化程序:将对象更改为包含对象的简单属性和值

时间:2015-07-03 12:44:28

标签: java json serialization jackson deserialization

我遇到的问题是我有一个在很多地方使用的公共对象,在这个例子中,常见的对象是Student。 Student是另一个名为Enrollment的对象的属性(但它可能是许多其他类的属性)。现在没有自定义序列化应用于学生我会得到这样的东西:

{"会话":"周三上午9点""学生":{" firstName":" Joe" " lastName的":"布罗格斯"}}

我想要做的是将自定义序列化程序应用于Student,以便它出现在我的代码中的任何位置,例如在Enrollment类中,我会得到这个:

{"会话":"周三上午9点"" firstName":" Joe"," lastName": "布罗格斯"}

或者如果我这样选择:

{"会话":"周三上午9点""第一":" Joe","最后": "布罗格斯"}

或者甚至可以这样:

{"会话":"周三上午9点""名称":" Joe Bloggs"}

这是我的示例代码:

public class Enrolment {

    private String session;
    private Student student;

    public Enrolment(String session, Student student) {
        this.session = session;
        this.student = student;
    }

    public String getSession() {
        return session;
    }

    public void setSession(String session) {
        this.session = session;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }
}

@JsonSerialize(using = StudentSerializer.class)
public class Student {

    private String firstName;
    private String lastName;

    public Student(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

public class StudentSerializer extends JsonSerializer<Student> {

    @Override
    public void serialize(Student value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        // ??????
    }
}

public class Launcher {

  public static void main(String[] args) throws Exception{

      ObjectMapper mapper = new ObjectMapper();
      Student student = new Student("Joe", "Bloggs");
      Enrolment enrolment = new Enrolment("9am Wednesday", student);

      System.out.println(mapper.writeValueAsString(enrolment));

  }
}

如果你也可以提供一个反序列化器,它可以接受一个所需的json序列化示例并从中创建Student对象,这将是一个巨大的奖励。同样,反序列化器就像序列化器必须连接到Student对象一样,这样它出现的任何地方都会执行相同的操作。

谢谢:)

2 个答案:

答案 0 :(得分:1)

您希望从版本1.9开始提供@JsonUnwrapped注释。您可以查看版本2.0 here的文档,但基本上您可以:

public class Enrolment {
    ...
    @JsonUnwrapped
    public Student getStudent() {
        return student;
    }
    ...
}

你会得到你的第一个选择:

{"session":"9am Wednesday","firstName":"Joe","lastName":"Bloggs"}

注释依赖于默认的序列化程序。一方面,您不能拥有Student的自定义序列化程序,但另一方面,您可以使用@JsonProperty等其他注释并自定义Student来获得第二个选项。

通过在Student中添加自定义getter和setter,您的第三个选项也会做得最好。在这种情况下,您将使用@JsonIgnore来避免序列化其他属性。

答案 1 :(得分:0)

这是我偶然发现的另一个选择:

public class Enrolment {

    private String session;
    private Student student;

    public Enrolment(String session, Student student) {
        this.session = session;
        this.student = student;
    }

    public String getSession() {
        return session;
    }

    public void setSession(String session) {
        this.session = session;
    }

    @JsonUnwrapped
    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }
}

public class StudentUnwrappingBeanSerializer extends UnwrappingBeanSerializer {

    public StudentUnwrappingBeanSerializer(BeanSerializerBase src, NameTransformer transformer) {
        super(src, transformer);
    }

    @Override
    public JsonSerializer<Object> unwrappingSerializer(NameTransformer transformer) {
        return new StudentUnwrappingBeanSerializer(this, transformer);
    }

    @Override
    protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {

        Student student = (Student) bean;
        jgen.writeStringField("first", student.getFirstName());
        jgen.writeStringField("last", student.getLastName());
    }

    @Override
    public boolean isUnwrappingSerializer() {
        return true;
    }
}

public class Launcher {

  public static void main(String[] args) throws Exception{

      ObjectMapper mapper = new ObjectMapper();

      mapper.registerModule(new Module() {
          @Override
          public String getModuleName() {
              return "my.module";
          }

          @Override
          public Version version() {
              return Version.unknownVersion();
          }

          @Override
          public void setupModule(SetupContext context) {

              context.addBeanSerializerModifier(new BeanSerializerModifier() {
                  @Override
                  public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                      if(beanDesc.getBeanClass().equals(Student.class)) {
                          return new StudentUnwrappingBeanSerializer((BeanSerializerBase) serializer, NameTransformer.NOP);
                      }
                      return serializer;
                  }
              });

          }
      });

      Student student = new Student("Joe", "Bloggs");
      ExtendableOption<StudyType> studyType = new ExtendableOption<>(StudyType.DISTANCE);
      Enrolment enrolment = new Enrolment("9am Wednesday", student, studyType);

      System.out.println(mapper.writeValueAsString(enrolment));

  }
}