3

I am using ObjectMapper to convert a JSON String to a Map but I get ClassCastException when trying to retrieve a value:

Map<String,String[]> args = objectMapper.readValue(jsonString, HashMap.class);
String[] array = args.get(paramName);

then doing

String x = array[0];

gives

java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.String

How can this be when I clearly specify String[] and not ArrayList, and when the second line doesn't cause any errors...

4
  • ArrayList is Java's implementation of a dynamic array (so therefore has an underlying String[] to store values) but I doubt that's what you're running into here. Commented Aug 21, 2012 at 19:09
  • 2
    The actual type is erased at runtime. I think yoru objectMapper returns a Map<String,ArrayList<String>>, not Map<String,String[]>. Commented Aug 21, 2012 at 19:10
  • @dasblinkenlight shouldn't that launch the ClassCastException at the previous line (String[] array = args.get(paramName);) Commented Aug 21, 2012 at 19:15
  • @SJuan76 Not necessarily, because the info of the type parameters is not available at runtime. Commented Aug 21, 2012 at 19:19

3 Answers 3

2

HashMap.class is the only information available to objectMapper at runtime.

It doesn't know that you declared a Map<String, String[]> on the left-hand side, so it does what most JSON mappers would do: It assumes you want a 1:1 map-based representation of the JSON which results in a Map<String, ArrayList<String>>.

Just use

List<String> list = args.get(paramName);
String x = list.get(0);

instead of String[] array and array[0].

Better yet, map your JSON into actual model classes, not a HashMap.

Sign up to request clarification or add additional context in comments.

2 Comments

i cannot change the type of args on the first line: Map<String, String[]>.. then when doing List<String> list = args.get(param) i expectedly get 'cannot convert from String[] to List'... how can i reconcile this
If you System.out.println(args) right after objectMapper.readValue(...), what does it print?
0

The object mapper does not obey (in fact cannot) the parameterized type information you used. It only knows about the class you are passing in as an argument. You'd be much better off using the generic type.

What you are actually getting back is:

Map<Object, Object> args = objectMapper.readValue(jsonString, HashMap.class);

I recommend changing your code to use something that for your arguments and then doing class casts and checking accordingly.

For example:

Map<Object, Object> args = new LinkedHashMap<Object, Object>();
Object value = args.get("foo");
String x;
if (value instanceof String[]) {
    String[] array = (String[])value;
    x = array[0];
} else if(value instanceof List) {
    List<Object> list = (List<Object>) value;
    x = String.valueOf(list.get(0));
} else {
    //error handling
}
...

Comments

0

Your diagnosis is incorrect. The line that throws the ClassCastException is

String[] array = args.get(paramName);

and not the later array access. The reason for the error to occur at this line is, I believe, obvious: the map value simply isn't an array, but is in fact an ArrayList.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.