Convert ArrayList from Gson to String

I have an ArrayList that contains ArrayLists , each ArrayList in the root list contains one ArrayList of Integers and one of Strings . I convert it from Gson to String to save it using SharedPreferences. But when I retrain it, Gson gives me 2.131558489E9 instead of the original int 2131558489 . How can I fix this problem? Best wishes.

This is how I convert an ArrayList: levelPattern is an ArrayList

 String levelPatternGson = new Gson().toJson(levelPattern); 

And here is how I convert it:

 levelPattern = new Gson().fromJson(levelPatternGson, ArrayList.class); 
+5
source share
2 answers

There is no difference in the json standard between integers and doubles, there is only a type of number. This is why gson converts numbers to doubles by default, unless you give it what type you want.

A simple fix will be to use TypeToken and change the data structure to multiple arrays or a custom object (for example, in the @totoro demo ).

 new Gson().fromJson(levelPatternGson, new TypeToken<List<Integer>>() {}.getType()); 

But you can also write your own list deserializer:

 public static class ListDeserializerDoubleAsIntFix implements JsonDeserializer<List>{ @Override @SuppressWarnings("unchecked") public List deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return (List) read(json); } public Object read(JsonElement in) { if(in.isJsonArray()){ List<Object> list = new ArrayList<Object>(); JsonArray arr = in.getAsJsonArray(); for (JsonElement anArr : arr) { list.add(read(anArr)); } return list; }else if(in.isJsonObject()){ Map<String, Object> map = new LinkedTreeMap<String, Object>(); JsonObject obj = in.getAsJsonObject(); Set<Map.Entry<String, JsonElement>> entitySet = obj.entrySet(); for(Map.Entry<String, JsonElement> entry: entitySet){ map.put(entry.getKey(), read(entry.getValue())); } return map; }else if( in.isJsonPrimitive()){ JsonPrimitive prim = in.getAsJsonPrimitive(); if(prim.isBoolean()){ return prim.getAsBoolean(); }else if(prim.isString()){ return prim.getAsString(); }else if(prim.isNumber()){ Number num = prim.getAsNumber(); // here you can handle double int/long values // and return any type you want // this solution will transform 3.0 float to long values if(Math.ceil(num.doubleValue()) == num.longValue()) return num.longValue(); else{ return num.doubleValue(); } } } return null; } } 

and use it as follows:

 GsonBuilder builder=new GsonBuilder(); List<List> levelPattern = Arrays.asList(Arrays.asList(2131558489L, 2L, 3L), Arrays.asList("one", "two", "three")); String levelPatternGson = new Gson().toJson(levelPattern); List levelPattern2 = new GsonBuilder() .registerTypeAdapter(List.class, new ListDeserializerDoubleAsIntFix()) .create() .fromJson(levelPatternGson, List.class); System.out.println(levelPattern2); 

Json: [[2131558489,2,3], ["one", "two", "three"]]

Output: [[2131558489, 2, 3], [one, two, three]]

+6
source

I'm not sure I fully understand the question ...

I assume your ArrayList not using generics.

This solution is a version of generics, using Object to store two different types of ArrayList s.

 class Test { static class Bar { private List<Integer> integers; private List<String> strings; } public static void main(String[] argv) { Type baseType = new TypeToken<List<Bar>>() {}.getType(); List<Bar> foos = new ArrayList<>(); Bar bar; bar = new Bar(); bar.integers = Arrays.asList(1, 2, 3, 4); bar.strings = Arrays.asList("a", "b", "c", "d"); foos.add(bar); bar = new Bar(); bar.integers = Arrays.asList(5, 6, 7, 2131558489); bar.strings = Arrays.asList("e", "f", "g", "h"); foos.add(bar); Gson gson = new Gson(); String tmp = gson.toJson(foos, baseType); System.out.println(tmp); foos = gson.fromJson(tmp, baseType); System.out.print(foos.get(1).integers.get(3)); } } 

Output

JSON: [{"Integers": [1,2,3,4], "strings": ["A", "B", "C", "D"]}, {"integers": [5 , 6.7, 2131558489], "strings": ["E", "F", "G", "h"]}]

Integer: 2131558489

+4
source

All Articles