Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - Object Mapper - JSON Array of Number to List<Long>

In my front end I send this JSON:

"ids": [ 123421, 15643, 51243],
"user": {
   "name": "John",
   "email": "[email protected]" 
}

To my Spring Endpoint below:

@PostMapping(value = "/sendToOficial")
public ResponseEntity<?> sendToOficial(@RequestBody Map<String, Object> payload) {

ObjectMapper mapper = new ObjectMapper();
List<Long> pointsIds = mapper.convertValue( payload.get("pointsIds"), List.class );
UsuarioDTO autorAlteracao = mapper.convertValue(payload.get("user"), UsuarioDTO.class);

for (Long idPoint : pointsIds) { ... }

But I'm getting a Cast Exception in the for saying that it can't cast Integer to Long.

I can't receive the "ids" numbers as Integer, I want to receive as Long. Please, how could I do this?

like image 348
WitnessTruth Avatar asked Oct 11 '18 13:10

WitnessTruth


3 Answers

First, define POJOs for mapping your request object:

public class RequestObj implements Serializable{

    private List<Long> ids;

    private UsuarioDTO user;

    /* getters and setters here */

}

public class UsuarioDTO implements Serializable{

    private String name;
    private String email;

    /* getters and setters here */

}

And then modify your endpoint:

@PostMapping(value = "/sendToOficial")
public ResponseEntity<?> sendToOficial(@RequestBody RequestObj payload) {

In this way you also do not need to use an ObjectMapper. Just call payload.getIds().

Consider also that in this way if payload changes you'll need only to change RequestObj definition, while using ObjectMapper would force you to update also your endpoint in an important way. It's better and safer to separate payload representation from control logic.

like image 130
Lorelorelore Avatar answered Nov 14 '22 22:11

Lorelorelore


In jackson-databind-2.6.x and onward versions you can configure the ObjectMapper to serialize low typed int values (values that fit in 32 bits) as long values using the DeserializationFeature#USE_LONG_FOR_INTS configuration feature:

@PostMapping(value = "/sendToOficial")
public ResponseEntity<?> sendToOficial(@RequestBody Map<String, Object> payload) {

    ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature .USE_LONG_FOR_INTS, true);
    List<Long> pointsIds = mapper.convertValue( payload.get("pointsIds"), List.class );
    UsuarioDTO autorAlteracao = mapper.convertValue(payload.get("user"), UsuarioDTO.class);

    for (Long idPoint : pointsIds) { // ... }

}
like image 31
tmarwen Avatar answered Nov 14 '22 23:11

tmarwen


If you just want your mapper to read into a List<Long>, use this trick for obtaining full generics type information by sub-classing.

Example

ObjectMapper mapper = new ObjectMapper();
List<Long>listOfLong=mapper.readValue("[ 123421, 15643, 51243]" ,
                    new TypeReference<List<Long>>() {
                    });
System.out.println(listOfLong);

Prints

[123421, 15643, 51243]
like image 44
jschnasse Avatar answered Nov 14 '22 22:11

jschnasse