Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting Object to Map: Cast vs ObjectMapper

What is the difference between below two methods of converting Object to Map? And which method is better, assuming both methods work for converting an Object to a Map?

Cast:

Object o = some object;
Map<String, Object> map = (Map<String, Object>) o;

ObjectMapper:

Object o = some object;
Map<String, Object> map = new ObjectMapper().readValue((String) o, new TypeReference<Map<String, Object>>() {});
like image 499
6324 Avatar asked Aug 28 '18 16:08

6324


2 Answers

That's depends what the input is.

  • (Map<String, Object>) o is used for casting conversion, so the runtime type of o must be Map, otherwise ClassCastException will be thrown:

    Object o = new HashMap<>();
    Map<String, Object> map = (Map<String, Object>) o; // ok
    
    Object o = new ArrayList<>();
    Map<String, Object> map = (Map<String, Object>) o; //ClassCastException
    
    Object o = new String();
    Map<String, Object> map = (Map<String, Object>) o; //ClassCastException
    
  • ObjectMapper().readValue(String content, JavaType valueType):

    Method to deserialize JSON content from given JSON content String.

    which means the input should be a String in valid json format. For example:

    Object input = "{\"key1\":{},\"key2\":{}}";
    Map<String, Object> map = new ObjectMapper().readValue((String) input, new TypeReference<Map<String, Object>>() {});
    
    System.out.println(map.size()); // 2
    
like image 86
xingbin Avatar answered Sep 30 '22 09:09

xingbin


There is no "better". There are practical differences. But first, both options use type casting, and this raises the question "how are these two considered alternatives at all?"

Casting will only work if some object passes the instanceof Map test (first option), or if o passes the instanceof String test (second option).

In other words, the answer depends on the runtime class of some object.

So either this will fail with a class cast exception:

(Map<String, Object>) o;

Or this will fail with the same exception:

(String) o 

Assuming the type checks will pass one way or the other, there are differences to be considered:

  • If some object is compatible with Map<String, Object>, then casting should be preferred as it offers a performance advantage (considering objectMapper.convertValue as the alternative). In fact, readValue isn't even an option as the cast to string will fail.
  • If some object is a String, then you have no choice but to call readValue, as you need to parse JSON.

As noted above, there's also objectMapper.convertValue, which in a smart way checks first instanceof before performing the conversion through JSON parsing. It's meant to convert objects from one type to another, if the two types have the same fields.

like image 22
ernest_k Avatar answered Sep 30 '22 09:09

ernest_k