java 使用 Gson 将 ArrayList 转换为字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37091548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 02:11:58  来源:igfitidea点击:

Convert ArrayList with Gson to String

javaandroidarraylistgsonsharedpreferences

提问by Chinaedu Onwukwe

I have an ArrayListwhich contains ArrayLists, each ArrayListin the Root list contains one ArrayListof Integersand one of Strings. I am converting it with Gson to a String to save it with SharedPreferences. But when I am reconverting it, Gson gives me 2.131558489E9instead of the original int 2131558489. How can I fix this Problem? Best Regards.

我有一个ArrayList包含ArrayListsArrayList在根列表中包含一个ArrayListIntegers和的一个Strings。我正在使用 Gson 将其转换为字符串以使用 SharedPreferences 保存它。但是当我重新转换它时,Gson 给了我2.131558489E9而不是原来的 int 2131558489。我该如何解决这个问题?最好的祝福。

Here is how I convert the ArrayList: levelPattern is the ArrayList

这是我转换 ArrayList 的方法: levelPattern 是 ArrayList

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

And this is how I convert it back:

这就是我将它转换回来的方式:

levelPattern = new Gson().fromJson(levelPatternGson, ArrayList.class);

回答by varren

There is no difference in json standard between integers and doubles, there is only number type. That is why gson by default converts numbers to doubles if you don't give him what type you want.

整数和双精度之间的json标准没有区别,只有数字类型。这就是为什么如果你不给他你想要的类型,默认情况下 gson 会将数字转换为双精度数。

Easy fix would be to use TypeTokenand change data structure to multiple arrays or custom object (like in @totorodemo).

简单的解决方法是使用TypeToken数据结构并将其更改为多个数组或自定义对象(如在@totorodemo 中)。

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

But you could also write custom List deserializer:

但您也可以编写自定义 List 反序列化器:

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 like this:

并像这样使用它:

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]]

Json: [[2131558489,2,3],["一","二","三"]]

输出:[[2131558489, 2, 3], [一, 二, 三]]

回答by totoro

I am not sure I understand the question completely...

我不确定我是否完全理解这个问题......

I am assuming your ArrayListis not using generics.

我假设您ArrayList没有使用泛型。

This solution is a generics version, using an Objectto hold the two different typed ArrayLists.

此解决方案是泛型版本,使用 anObject来保存两个不同类型的ArrayLists。

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"]}]

The Integer: 2131558489

JSON: [{"integers":[1,2,3,4],"strings":["a","b","c","d"]},{"integers":[5,6 ,7,2131558489],"strings":["e","f","g","h"]}]

整数:2131558489