Using Java records for (de-)serializing complex/nested objects to JSON

Viewed 30

Given the following JSON...

{
  "loginData": {
    "username": "foobar",
    "password": "secret"
  },
  "personalData": {
    "givenName": "Foo",
    "familyName": "Bar"
  }
}

This is what my POJO (with some maybe verbose Lombok annotations) looks like. It gets (de-)serialized by Jackson:

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class User {

    private LoginData loginData;
    private PersonalData personalData;

    @Builder
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class LoginData {
        private String username;
        private String password;
    }

    @Builder
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class PersonalData {
        private String givenName;
        private String familyName;
    }
}

I wonder if it is possible to replicate this structure using the relatively new concept of a Java record. I'm aware of a simple record like:

public record LoginData(String username, String password) {}

But can records also be used for nested/complex objects which shall be converted to JSON with Jackson?

1 Answers

From what I understood you can use records similar to normal objects/classes. This also means you can use records as parameters for other records. I created a simple example for converting your input JSON string to a nested object with records:

Interface defining three records:

public interface IRecord {
    record LoginData(String username, String password) {};
    record PersonalData(String givenName, String familyName) {};
    record Data(LoginData loginData, PersonalData personalData) {};
}

Main class to test:

public class Main {

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

        ObjectMapper mapper = new ObjectMapper();
        String jsonInString = "{\"loginData\": {\"username\": \"foobar\",\"password\": \"secret\"}, \"personalData\": {\"givenName\": \"Foo\", \"familyName\": \"Bar\"}}";

        IRecord.Data user = mapper.readValue(jsonInString, IRecord.Data.class);
        System.out.println(user.loginData().username());
    }
}

Output:

foobar
Related