0

I have an object which has a map inside it:

MyDTO 
   HashMap<Integer> 

Now when I convert my MyDTO to JSON (with Gson), and then back from JSON to MyDTO what I get is HashMap<String>.

I convert from JSON back to object like this:

MyDTO dto = gson.fromJson(json, MyDTO.class);

How can I force it to convert/keep the Map inside the DTO as Map<Integer> and NOT as Map<String>?

Here is my Object:

public class MultiSeriesTimebasedChartDTO implements Serializable
 {

    LinkedHashMap<String, ArrayList<Number>> data;
}

Here's how I convert my JSON back to object:

multiSeriesTimebasedChartDTO = gson.fromJson(json, MultiSeriesTimebasedChartDTO.class);

And here is the result (in screenshot), which were Numbers but now are Strings. I needed them back as Numbers.

Debugger screenshot showing object values

So looking for a clean approach for this.

I can definitely iterate over it, change every number from string back to number, and replace it... But I was thinking may be there is some other better way of oing it.

5
  • as Map<Integer> and not as Map<String> , because after i convert back to my object from json , The Map inside my object which was type Integer , Its not converted to a type String , So everything inside my map is now String ,which were integers actually Commented Sep 4, 2020 at 6:42
  • 1
    Show your DTO and source JSON Commented Sep 4, 2020 at 6:45
  • Map<Integer> is not a valid Java type, since a Map requires 2 type arguments. Did you mean Map<String, Integer> or perhaps Map<Integer, Integer>? Normally, a Map is converted to a JSON Object, and since a JSON Object is a set of name/value pairs, the keys in the Map are converted to strings, because JSON property names must be strings. Is that what you're referring to? Commented Sep 4, 2020 at 6:56
  • I added details in my question Commented Sep 4, 2020 at 7:01
  • can you show your map .put( ) line(s) ? Or your data = anything line? Commented Sep 4, 2020 at 7:08

2 Answers 2

1

The values are still java.lang.Numbers after the JSON is parsed. However, because your field has the type LinkedHashMap<String, ArrayList<Number>>, Gson uses its internal type LazilyParsedNumber because it cannot know as which specific type you want the Numbers to be parsed. LazilyParsedNumber acts as a wrapper for the JSON string representation so you can call the respective Number method to parse the value.

LazilyParsedNumber should suffice if you are only retrieving its intValue(), doubleValue() ..., but if want to compare it with other Numbers it wont work since LazilyParsedNumber is only equal to itself.

Since your question mentions that the Map contains Integer values, the easiest solution would be to change the type of the DTO field:

LinkedHashMap<String, ArrayList<Integer>>

This way Gson knows the exact number type you want and can properly deserialize the JSON numbers as Integers.

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

Comments

0

You have no "HashMap<Integer>" whatever that could be, you have ArrayList<Number>, and that is what GSON has to prepare for:

public class MultiSeriesTimebasedChartDTO implements Serializable{
  LinkedHashMap<String, ArrayList<Number>> data;
                        ^^^^^^^^^^^^^^^^^
}

Also, you don't have Strings what you complain about, those are LazilyParsedNumbers,

And while it really stores the value as a string, that class indeed is a Number. You don't have to worry about its private member variables.

public final class LazilyParsedNumber extends Number { // <= extends Number
  private final String value;  // <= this is what you see in the debugger

But that is just the explanation about what's there now. If you want GSON to produce you a list of Integers, you should simply write that:

public class MultiSeriesTimebasedChartDTO implements Serializable{
  LinkedHashMap<String, ArrayList<Integer>> data;
}

remember that GSON can only analyse the declaration of the class, it can't guess if you later ensure that all those generic numbers are integers.

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.