【问题标题】:JSON String to Java object using GSON使用 GSON 将 JSON 字符串转换为 Java 对象
【发布时间】:2013-05-19 08:35:14
【问题描述】:

我正在尝试将 json 解析为 java。

根据 jsonlint.com,我有以下是有效 json 的字符串

private final static String LOC_JSON = 
         "["
        +"{"
        +"  \"lat1\": 39.737567,"
        +"  \"lat2\": 32.7801399,"
        +"  \"long1\": -104.98471790000002,"
        +"  \"long2\": -96.80045109999998"
        +"},"
        +"  ["
        +"      {"
        +"          \"lat\": {"
        +"              \"b\": 38.88368709500021,"
        +"              \"d\": 40.620468491667026"
        +"          },"
        +"          \"long\": {"
        +"          \"b\": -105.75306170749764,"
        +"          \"d\": -104.675854661387"
        +"          }"
        +"      }"
        +"  ]"
        +"]";

我正在尝试将其解析为一个对象,但出现以下错误。 "预期为 BEGIN_OBJECT,但在第 1 行第 2 列是 BEGIN_ARRAY"

            Gson gson = new Gson();
        BoxSearch b = gson.fromJson( LOC_JSON, BoxSearch.class ); 

BoxSearch 由这个组成。

private Number lat1;
private Number lat2;
private Number long1;
private Number long2;
private Boxes[] boxes;

Boxes 是定义相同的纬度对象和经度对象。

private String b;
private String d;

我可以将更高级别的属性(lat1、lat2、long1 和 long2)解析成一个更简单的 BoxSearch 对象,它只有这 4 个属性。当 json 和对象更复杂时,麻烦就来了。甚至可以做我正在尝试的事情吗?

我希望我已经提供了足够的信息来获得帮助。如果需要,我很乐意提供更多信息甚至是测试项目。我将其作为 junit 测试运行。

谢谢。

【问题讨论】:

  • GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"? 的可能重复项 - 您的 JSON 是一个数组,而不是一个对象。但是你会遇到问题,因为它是一个包含不同类型对象(一个对象和一个数组)的数组,如果不编写自定义反序列化器,你就无法处理
  • @BrianRoach 这更像是一个答案;)
  • @RC。是的……嗯。我想也许我会移动它,老 Q 回答了他为什么会收到错误,但他的案例的解决方案是不同的
  • 我确实经历了可能的重复,但该对象是简单的而不是复杂的。有没有更好的方法来组织 json 字符串?我的 UI 将它放在一起(基于谷歌地图),但我可以操纵它。我想我会尝试更简单/更扁平的对象。还是编写自定义反序列化器?
  • @user2415153 - 请参阅下面的扩展答案。如果您是生成 JSON 的人,那么是的 - 重做它以使其成为对象而不是数组将使您的生活更轻松。让我在回答中对此进行一些扩展;编辑。

标签: java json parsing gson


【解决方案1】:

错误的原因是您的顶级 JSON 是一个数组,而不是一个对象。 GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"? 涵盖了这一点。

但是,那里的解决方案不适用于您的 JSON,因为您有一个混合类型(对象和数组)的数组,而不是单一类型对象的数组。为此,您将不得不编写自定义反序列化器(请参阅The section of the Gson user's guide that covers this)或直接使用 Gson 的 JsonParser 类并从解析树中提取数据。

从上面的 cmets 编辑:

如果您是创建 JSON 的人,看起来您想要的是 BoxSearch 对象的数组?

根据您的 Java BoxSearch 类,您需要 JSON 结构如下:

[
    {
        "lat1" : 39.737567,
        "lat2" : 32.7801399,
        "long1" : -104.98471790000002,
        "long2" : -96.80045109999998,
        "boxes" : [ 
                    {
                      "lat": {
                          "b": 38.88368709500021,
                          "d": 40.620468491667026
                      },
                      "long": {
                          "b": -105.75306170749764,
                          "d": -104.675854661387
                      }
                    }
                  ]
    }
]

但是,您定义 Boxes 类的方式不适用于此。 (你的意思是有一个数组吗?)。原样它需要看起来像:

class Boxes {
    Box lat;
    @SerializedName("long")
    Box lon;
}

class Box {
   String b;
   String d;
}

现在您有一个包含一种类型的对象 (BoxSearch) 的数组,您可以使用它进行反序列化:

Type collectionType = new TypeToken<Collection<BoxSearch>>(){}.getType();
Collection<BoxSearch> boxSearchCollection = gson.fromJson(json, collectionType);

如果您真的不需要这些数组,请摆脱外部数组并简单地执行以下操作:

gson.fromJson(json, BoxSearch.class);

【讨论】:

  • 非常感谢布赖恩,对 json 的细微调整,一切都很好。我会投票赞成这个答案,但我没有“街头信誉”。代码像冠军一样工作。如果人们复制并粘贴此答案,请框长;需要重命名:-)
  • 哦,是的,我需要数组。再次感谢。
  • @user2415153 我更改了代码,因此它可以在 JSON 中与 "long" 一起使用 - 现在查看答案 :) 我没有注意到,抱歉。至于投票 - 你可以接受我的回答;)很高兴我能提供帮助!
  • 奇特的解决方案!我只是将变量重命名为完整的单词。接受回答!再次感谢!
【解决方案2】:
Gson gson = new Gson();
gson.fromJson(jsonStr,YourClass.class);

很简单。

【讨论】:

  • 它可以帮助我转换一个包含列表的 json 对象。我将 json 字符串转换为 Object.class
猜你喜欢
  • 1970-01-01
  • 2017-01-24
  • 1970-01-01
  • 2021-10-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 2018-01-20
相关资源
最近更新 更多