javaspringspring-boot

Spring boot: Creating JPA Entities from raw JSON


I am building a REST API using Spring boot and hibernate. Now I want to create a POST method that gets a JSON. After some validations, I want to save this object as a new entity in my DB. I was wondering how to convert the map of attributes to a new User entity? I have the following classes:

User.java

@Entity
@Table(name="users")
@JsonIdentityInfo(generator= ObjectIdGenerators.IntSequenceGenerator.class, property="id")
public class User {
    
    @Transient
    Logger logger = LogManager.getLogger(getClass());

    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int ID;
    
    @NotNull
    private String username;
    
    @NotNull
    private String Last_Name;
    @NotNull
    private String First_Name;

    private String Title;

//...

}

UserController.java

@PostMapping("/user") 
public ResponseEntity test(@RequestBody Map<String,Object> object) throws Exception {
    try {
        userService.createAccount(object);
    } catch (IllegalArgumentException e) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
    }
    return ResponseEntity.ok("Account was added successfully");
}

UserService.java

public void createAccount(Map<String, Object> accountObject) throws Exception {
        logger.trace("Entering createAccount(). account=" +accountObject);
        User user = new User( ??? );
        userRepository.save(user);
  }
            

I was thinking of creating a new constructor in User.java that maps every MapEntry to a field, but I was wondering if there is a better approach?

public User(Map<String, Object> fieldsMapping) {
        this(
            getValue(fieldsMapping, "username", String.class),
            getValue(fieldsMapping, "last_name", String.class),
            getValue(fieldsMapping, "first_name", String.class),
        );
    }

    // Helper method for type-safe value extraction.
    private static <T> T getValue(Map<String, Object> map, String key, Class<T> clazz) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        }
        return clazz.cast(value);
    }

Solution

  • You can use Jackson's ObjectMapper to convert a map of values to another class. But be sure to use @JsonIgnoreProperties(ignoreUnknown = true) in your User class, otherwise it will give you errors if unecessary properties are present. Example:

    Map<String, Object> request = new HashMap<>();
    request.put("username", "myName");
    request.put("Last_Name", "myLastName");
    
    ObjectMapper objectMapper = new ObjectMapper();
    User user = objectMapper.convertValue(request, User.class);
    

    Also you need to make sure about the Json mappings using @JsonProperty annotation.

    Just for reference, I don't think it's a good idea to do this based on the comments you gave saying you intend to map /users to two different entities, I would advise creating two distinct endpoints using two distinct DTOs, and the caller decides which one to use.