【问题标题】:Deserializing json array using gson使用 gson 反序列化 json 数组
【发布时间】:2011-03-28 09:35:51
【问题描述】:

this question继续。

我在反序列化以下 json 数组时遇到了问题(对不起大小):

"geometry": { "type": "Polygon", "coordinates": [ [ [ 771230.894373, 4422896.962001 ],
 [ 804804.852796, 4451159.130080 ], [ 876828.563339, 4417873.954498 ], [ 959794.979827, 
4430944.287708 ], [ 910992.515063, 4372980.866944 ], [ 932488.308736, 4357684.778349 ], 
[ 918573.372386, 4115663.286966 ], [ 834059.614976, 4013708.358795 ], [ 929360.231044, 
3833522.241529 ], [ 1008029.715188, 3776446.653183 ], [ 1061663.445852, 3533717.758754      
], [ 1035703.740599, 3519308.069656 ], [ 1095348.723766, 3396028.487184 ], [ 
1108462.159782, 3230455.268230 ], [ 1083571.121640, 3163122.508021 ], [ 1103953.720405, 
3082716.041755 ], [ 1045722.494771, 3020215.642212 ], [ 1117367.719045, 2915275.458735 
], [ 1141268.013718, 2827405.304519 ], [ 1286729.192338, 2790314.754276 ], [ 
1334329.406601, 2695307.513404 ], [ 829417.592210, 2374337.277646 ], [ 647042.870444, 
2207530.090128 ], [ 370914.873531, 2152159.656850 ], [ 346669.488436, 2173360.227237 ], 
[ 359905.375891, 2251757.174668 ], [ 199905.871774, 2309591.361246 ], [ 129963.835709, 
2361036.252651 ], [ 130208.738589, 2404106.913263 ], [ -964785.432600, 3159802.671416 
], [ -964829.960396, 3338713.127631 ], [ -851005.781060, 3424742.002477 ], [ -
616522.405653, 3491025.523892 ], [ -547749.224241, 3569019.334331 ], [ -403724.067052, 
3628920.873754 ], [ -423973.082428, 3724062.779415 ], [ -333893.350478, 3741450.793542 
], [ -317696.364567, 3774909.265404 ], [ -131414.328674, 3777826.527844 ], [ -
112467.751341, 3830221.719769 ], [ -185682.580436, 3930014.456814 ], [ -194499.084106, 
4129581.855629 ], [ -245950.952751, 4175549.526399 ], [ -42303.076294, 4287174.981681 
], [ -11222.674464, 4271148.905617 ], [ 131633.628071, 4371332.547494 ], [ 
433220.392528, 4427574.250017 ], [ 593119.709103, 4389089.571176 ], [ 719645.442339, 
4451856.882422 ], [ 771230.894373, 4422896.962001 ] ] ] }

如果我将它粘贴到 json-viewer 中,我会得到这个结构:

[geometry]
...
[coordinates] => Array
    (
        [0] => Array
            (
                [0] => Array
                    (
                        [0] => 771230.894373
                        [1] => 4422896.962001
                    )
                [1] => Array
                    (
                        [0] => 804804.852796
                        [1] => 4451159.13008
                    )
                ...
                [n] => Array
        [n] => Array

现在,包含具有坐标的数组的数组具有可变大小。所以我想在java中,这整个对象应该是一个数组,包含数组的集合,每个数组都包含一个Collection<double[]>。类似Collection<double[]>[][].

但是 gson 不接受这个。我收到以下错误消息:

Exception in thread "main" com.google.gson.JsonParseException: Expecting object but     
found array: 2.963610

这看起来很奇怪,因为 2.963610 在我看来不像一个数组。但这可能让我感到困惑,或多或少地迷失了......

【问题讨论】:

    标签: java json serialization gson


    【解决方案1】:

    我认为我们需要更多详细信息,例如您为反序列化编写的内容。

    【讨论】:

    • 我只是这么写的:Data data = new Gson().fromJson(json.toString(),Data.class); Data 对象是一个简单的 java 对象,具有字段的 getter 和 setter,共享 json 属性的名称。坐标是这些属性之一,可在 Geometry 类中找到。
    【解决方案2】:

    我想我知道你的问题来自哪里,阅读 Gson API:

    如果你的对象是 序列化/反序列化是 ParameterizedType(即包含在 至少一个类型参数,并且可能是 数组)那么你必须使用 toJson(对象,类型)或 fromJson(String, Type) 方法。这是 序列化和示例 反序列化 ParameterizedType:

    Type listType = new TypeToken<LinkedList>() {}.getType();
    List target = new LinkedList();
    target.add("blah");
    
    Gson gson = new Gson();
    String json = gson.toJson(target, listType);
    List target2 = gson.fromJson(json, listType);
    

    知道

    Type typeOfCollectionOfFoo = new TypeToken<Collection<Foo>>(){}.getType() 
    

    希望这会有所帮助。

    【讨论】:

    • 这可能是我的问题的一部分。我试过这个:类型坐标 = new TypeToken>>>(){}.getType();但这只是给了我一个错误消息,说它无法反序列化 [jsonstring]。
    • 偶然发现了这个老问题 - 接受了你的回答 :)
    【解决方案3】:

    JSON 中的coordinates 是一个三维矩阵。使用Collection&lt;double[]&gt;[][],您将一维走得太远。 Collection 本身已经是一维的,所以你基本上已经声明了一个四维矩阵。

    通过错误消息,Gson 基本上是在告诉您它期待一个第四维度的对象,但它却遇到了一个双精度对象。

    以下表示应由 Gson 完美处理的有效 3 维矩阵:

    • private double[][][] coordinates;(推荐)
    • private Collection&lt;double[]&gt;[] coordinates;
    • private Collection&lt;double[][]&gt; coordinates;
    • private Collection&lt;Collection&lt;double[]&gt;&gt; coordinates;
    • private Collection&lt;Collection&lt;Collection&lt;Double&gt;&gt;&gt; coordinates;

    也就是说,在这种特殊情况下,我更喜欢List 而不是Collection。使用List,您可以保证它已被插入订单填充,并且您将能够按索引get 元素。

    【讨论】:

    • 这似乎是正确的,除了 [coordinates] 数组中的外部数组的数量不是固定的。在我的示例中,只有 1 个。(它是 [coordinates] => Array( [0] => Array ( [0] => array ... ) ),但它也可以包含 2 个数组:[coordinates ] => Array ( [0] => Array ( ... ) [1] => Array ( ... ) ) 希望这是有道理的?所以我想我们需要另一个集合(或列表)?
    • 如果我只是添加另一个维度,例如私有 Collection>>> 坐标;我得到了这个异常:线程“main”com.google.gson.JsonParseException中的异常:JsonDeserializer com.google.gson.DefaultTypeAdapters$CollectionTypeAdapter@929206 failed to deserialized json object 2.963610 given type com.google.gson.ParameterizedTypeImpl@b6a924
    • 然后创建一个表示坐标的包装对象,该对象可以将子对象保存在集合中,并通过扩展JsonDeserializer 实现自定义反序列化器。
    【解决方案4】:

    根据 Gson 用户指南:

    对泛型类型进行序列化和反序列化
    当您调用 toJson(obj) 时,Gson 会调用obj.getClass() 来获取有关要序列化的字段的信息。同样,您通常可以在fromJson(json, MyClass.class) 方法中传递MyClass.class 对象。只要对象是非泛型类型,它就可以正常工作。但是,如果对象是泛型类型,那么泛型类型信息会因为Java Type Erasure 而丢失。这是一个说明这一点的例子:

    List<String> myStrings = new List<String>();
    gson.toJson(myStrings); // Will cause a runtime exception
    
    gson.fromJson(json, myStrings.getClass());
    

    上述调用导致运行时异常,因为 Gson 调用 myStrings.getClass() 来获取其类信息,但此方法返回一个原始类,List.class。这意味着 Gson 无法知道这是一个字符串列表,而不是普通对象。

    您可以通过为泛型类型指定正确的参数化类型来解决此问题。您可以使用TypeToken 类来做到这一点。

    Type listType = new TypeToken<List<String>>() {}.getType();
    gson.toJson(myStrings, listType);
    
    gson.fromJson(json, listType);
    

    用于获取listType 的习语实际上定义了一个匿名本地内部类,其中包含一个返回完全参数化类型的方法getType()

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2015-02-24
      • 2017-07-31
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多