Home > Software design >  Convert object to string Spring Boot rest API
Convert object to string Spring Boot rest API

Time:10-21

I'm receiving an id (integer) and a executor (String) in my controller (Rest API). However, when looking at my database, I see that the string is being inserted into the database as an object. Example of database entry:

{
    "executor": "Pietje"
}

Controller:

@PostMapping(path = "/accept/{id}")
public String acceptAssignment(@Valid @PathVariable Integer id, @RequestBody String executor) {
    return assignmentService.acceptAssignment(id, executor);
}

Service implementation:

@Override
public String acceptAssignment(Integer id, String executor) {
    Assignment assignment = assignmentRespository.findById(id).orElse(null);
    
    assignment.setExecutor(String.valueOf(executor));
    
    AssignmentDTO assignmentDTO = assignmentConverter.convertEntityToDto(assignment);
    
    assignmentRespository.save(assignment);
    
    return assignmentDTO.getExecutor();
}

What am I doing wrong, and how can I fix it?

I could pass along the entire DTO instead of just the 'executor' value, but that doesn't seem efficient. As far as I know, the problem is not with the frontend but I could add the React code if necessary.

CodePudding user response:

You can use ObjectMapper to fetch the desired key-value from the @RequestBody String executor as:

Approach Here:

The @RequestBodythat you are getting from the API is in the object form and using ObjectMapper , it will be converted into a Map of attributes as in the API request and we can fetch the desired key-value pair.

ObjectMapper mapper = new ObjectMapper();
Map<String,Object> map = mapper.readValue(executor, new TypeReference<>() {});
String s = (String) map.get("executor");

Added in acceptAssignment method as:

 @Override
  public String acceptAssignment(Integer id, String executor) throws JsonProcessingException {

    ObjectMapper mapper = new ObjectMapper();
    Map<String,Object> requestMap = mapper.readValue(executor, new TypeReference<>() {});
    Assignment assignment = assignmentRespository.findById(id).orElse(null);
    assignment.setExecutor((String)requestMap.get("executor"));
    AssignmentDTO assignmentDTO = assignmentConverter.convertEntityToDto(assignment);
    assignmentRespository.save(assignment);

    return assignmentDTO.getExecutor();
  }

CodePudding user response:

TL;DR - you're using a String containing a JSON-object as if it was an attribute of this JSON-object. The solution it to tread this JSON properly.

Note that you don't need to mess with desirialization manually, let the JSON-converter of the framework do its job.

All that you need is a simple POJO:

@Getter
@Setter
public static class AssignmentExecutor {
    private String executor;
}

The above POJO can be automatically translated in & to the following of JSON without any effort from your side (owing to the magic of Spring):

{
    "executor": "Pietje"
}

It would be automatically parsed to the proper type by a Spring's message-converter, you only need to specify that you need an AssignmentExecutor instead of a plain String.

@PostMapping(path = "/accept/{id}")
public String acceptAssignment(@Valid @PathVariable Integer id,
                               @RequestBody AssignmentExecutor executor) {
    
    return assignmentService.acceptAssignment(id, executor);
}

Note

  • Introducing this new type would not require any changes in the Assignment, executor can still be represented as a String field.
  • By invoking orElse(null) on the optional result, you're creating a potential problem by depriving the possibility to get a meaningful exception in case if the data that corresponds to the given id was not found instead of NullPointerException, which would be triggered on the next line. I would advise providing a suitable exception via Optional.orElseThrow().

A now again all that you need is to return an instance of AssignmentExecutor and it would be automatically converted into JSON:

@Override
public String acceptAssignment(Integer id, AssignmentExecutor executor) {
    Assignment assignment = assignmentRespository.findById(id)
        .orElseThrow(() -> new MyException("Assignment with id "   id   " was not found"));
    
    assignment.setExecutor(executor.getExecutor());
    assignmentRespository.save(assignment);
    
    return executor;
}
  • Related