Here is an example DTO
@Getter
@Setter
public class TestDto {
private Long id;
private String name;
private String sex;
}
Say I have this object stored on the server:
{"id":1, "name": "alex", "sex": "M"}
How can I send a request that only updates the "name" portion of the object?
Perhaps I could send this:
{"id":1, "name":"adam"}
Such that the object will change to this:
{"id":1, "name": "adam", "sex": "M"}
I also need the ability to set a field to null (i.e. clear the contents of a field).
In this case I would like to send
{"id":1, "name":"adam", "sex":null}
To have the stored DTO change to
{"id":1, "name": "adam", "sex":null}
How can I do this using java, spring boot, etc.?
I know the way to use:
@PutMapping
public TestDto update(Map<String, Object>map){ ... }
but I also need to some validation such that if I pass
{"id":"1AA" ... }
I get a serialization exception.
Ps.Find first step of this magic -> 1.Before path TestDto throu Rest - need to clear Type like this
Object body = testDto;
if will help you to get an Object with field what you want on server and then you'll be able to detect list of fieds to update
CodePudding user response:
Instead of attempting to detect absent vs null value, consider defining an update object that includes a list of fields to be updated.
Such an object might look like this:
@Getter
@Setter
public class UpdateObject
{
private long id; // ID of the object to be updated.
private TestDto updates; // an object that contains the new values for the fields.
private List<String> updateFields; // a list of fields to be updated.
}
Here is some Json
{
"id": 1,
"updates":
{
"name": "blem",
"sex": null
},
"updateFields": ["name", "sex"]
}
CodePudding user response:
if i understood right you just send request to the server with different fields. With @ModelAttribute
annotation you can send your body in json format.
if you send only one/two field or how you want {"id":1, "name":"adam"}
, due to spring data jpa you can update your model in db. (in this case your field sex
will be null and you need to create some manipulation for checking it kind of Mapstruct - convert your dto in other model plus checking null/not null fields).
Better create default value for sex
field if you want to saving not M and not FM values. null bad practice, in the future it will be bad joke for you.
@Getter
public Enum Sex {
private MALE,
private FEMALE,
private DEFAULT
}
CodePudding user response:
Ok guys finally fount how to do this
1.Client side - > path your testDto as Object, not as TestDto.class
Object payLoad = testDto;
template.postForObject("url", payload);
2.Server side - >
@RestController
@RequestMapping("/test")
public class TestController {
private final Map<Long, TestDto> cash = new HashMap<>();
private final ObjectMapper mapper = new ObjectMapper();
@PostMapping
public TestDto create(@RequestBody TestDto dto) {
return cash.computeIfAbsent(dto.getId(), v -> dto);
}
@PutMapping("/{id}")
public TestDto update(@PathVariable Long id, @RequestBody String json) throws JsonProcessingException {
val oldValue = cash.get(id);
mapper.readerForUpdating(oldValue).readValue(json);
return cash.put(oldValue.getId(), oldValue);
}
}
this hint let you update only field that client really changed