I have a controller that accepts ObjectNode as @RequestBody.
That ObjectNode represents json with some user data
{
"given_name":"ana",
"family_name": "fabry",
"email": "[email protected]",
"password": "mypass",
"gender": "FEMALE"
}
Controller.java
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public JsonNode createUser(@RequestBody ObjectNode user){
return userService.addUser(user);
}
I want to get user as ObjectNode convert it to Java POJO save it to database and again return it as JsonNode.
UserServiceImpl.java
private final UserRepository userRepository;
private final UserMapper userMapper;
@Override
public JsonNode addUser(@RequestBody ObjectNode user) {
try {
return userMapper.fromJson(user)
.map(r -> {
final User created = userRepository.save(r);
return created;
})
.map(userMapper::toJson)
.orElseThrow(() -> new ResourceNotFoundException("Unable to find user"));
} catch (RuntimeException re) {
throw re;
}
}
To convert ObjectNode to POJO
I did this in my UserMapper class:
public Optional<User> fromJson(ObjectNode jsonUser) {
User user = objectMapper.treeToValue(jsonUser, User.class);
}
Also, to write object to JsonNode I did this:
public JsonNode toJson(User user) {
ObjectNode node = objectMapper.createObjectNode();
node.put("email", user.email);
node.put("password", user.password);
node.put("firstName", user.firstName);
node.put("lastName", user.firstName);
node.put("gender", user.gender.value);
node.put("registrationTime", user.registrationTime.toString());
return node;
}
User.java
@Document(collection = "user")
@Builder
@AllArgsConstructor
public class User {
@Indexed(unique = true)
public final String email;
@JsonProperty("password")
public final String password;
@JsonProperty("firstName")
public final String firstName;
@JsonProperty("lastName")
public final String lastName;
@JsonProperty("gender")
public final Gender gender;
@JsonProperty("registrationTime")
public final Instant registrationTime;
public static User createUser(
String email,
String password,
String firstName,
String lastName,
Gender gender,
Instant registrationTime){
return new User(email, password, firstName, lastName, gender, registrationTime);
}
}
When I run my application, this is the error I am receiving:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.domain.User` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
I have read about the error, and it seems this error occurs because Jackson library doesn't know how to create a model which doesn't have an empty constructor and the model contains a constructor with parameters which I annotated its parameters with @JsonProperty("fieldName"). But even after applying @JsonProperty("fieldName") I am still getting the same error.
I have defined ObjecatMapper as Bean
@Bean
ObjectMapper getObjectMapper(){
return new ObjectMapper();
}
What am I missing here?
I could reproduce the exception. Then I added an all-args constructor with each parameter annotated with the right @JsonProperty.
@JsonCreator
public User(
@JsonProperty("email") String email,
@JsonProperty("password") String password,
@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("gender") String gender,
@JsonProperty("registrationTime") Instant registrationTime){
super();
this.email = email;
this.password = password;
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.registrationTime = registrationTime;
}
Now, it creates the instance, but I get other mapping errors (Unrecognized field "given_name") which you should be able to resolve.
Register Jackson ParameterNamesModule, which will automatically map JSON attributes to the corresponding constructor attributes and therefore will allow you to use immutable classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With