【问题标题】:Deserialize JSON object that has a map using Gson使用 Gson 反序列化具有地图的 JSON 对象
【发布时间】:2013-11-22 20:55:13
【问题描述】:

我在网上搜索了一个解决方案,但是,我找到的答案只有在被解析的 JSON 文件只是一张地图时才有帮助。

我想知道是否有办法解析具有HashMap 以及其他数据的对象。

例如:

public class Data
{
  String aName;
  HashMap<String, Object> objects;
  List<String> aExpressions;
}

我可以解析名称和表达式,但我不知道如何将整个 JSON 对象作为一个整体进行解析。

我认为它与类型标记有关,但仅当整个对象是 HashMap 时才有效。

【问题讨论】:

  • 你认为 JSON 是什么?它是使用标准符号组合在一起的列表和地图以及字符串和数字。只要您的 List 或 Map 仅(递归地)包含 Lists、Maps、Strings、Booleans 和 numbers(以及您用于 NULL 的任何内容),它就可以轻松转换为 JSON。
  • (Java 的一个问题是标准的 Java JSON 工具包掩盖了表示法的简单性。)

标签: java json hashmap gson


【解决方案1】:

您的类中 HashMap 的存在不会改变 Gson 将其转换为 json 和从 json 转换的方式。

data d = new data();
//set some values

String json = new Gson().toJson(d);
data d2 = new Gson().fromJson( json, data.class);

差不多了。

【讨论】:

【解决方案2】:

Since

JSON 可以表示四种基本类型(字符串、数字、 booleans 和 null)和两种结构化类型(对象和数组)。

字符串是零个或多个 Unicode 字符的序列 [UNICODE]。

对象是零个或多个名称/值的无序集合
对,其中名称是字符串,值是字符串、数字、
布尔值、空值、对象或数组。

数组是零个或多个值的有序序列。

Gson 有两种行为方式:

  1. 您可以让 Gson 反序列化创建映射、列表和原语的组合,或者
  2. 您可以准确地指定所需的对象类型,并通过反射填充所需的字段。

您可以混合使用这两种方法,当然您可以做更多的事情来解决所有解析情况(例如使用自定义类型适配器)。

我为您准备了一个使用您的类的小示例,该示例展示了 Gson 如何使用映射/列表/基元的组合或传递您的类(采用混合方法)来解析您的数据。

package stackoverflow.questions;

import java.util.*;

import com.google.gson.Gson;

public class Q20154323 {

   public static class Data {
      public String aName;
      public HashMap<String, Object> objects;
      public List<String> aExpressions;

      @Override
      public String toString() {
         return "Data [aName=" + aName + ", objects=" + objects + ", aExpressions=" + aExpressions + "]";
      }

   }

   public static void main(String[] args) {

      Data d = new Data();
      d.aName = "Test";
      d.objects = new HashMap<>();
      d.aExpressions = new ArrayList<>();

      d.objects.put("key1", 1L);
      d.objects.put("key2", new Date());
      d.aExpressions.add("Stack");
      d.aExpressions.add("Overflow");

      Gson g = new Gson();
      String json = g.toJson(d);
      System.out.println("As JSON: " +json);

      Data d2 = g.fromJson(json, Data.class);
      System.out.println("As \"casted\" data type: " + d2);

      Object o3 = g.fromJson(json, Object.class);
      System.out.println("As \"free\" object: " + o3);

   }

}

这就是执行。它向您展示了解析我使用您的初始类创建的 JSON 字符串的两种方法。

As JSON: {"aName":"Test","objects":{"key2":"Nov 23, 2013 1:33:23 AM","key1":1},"aExpressions":["Stack","Overflow"]}
As "casted" data type: Data [aName=Test, objects={key2=Nov 23, 2013 1:33:23 AM, key1=1.0}, aExpressions=[Stack, Overflow]]
As "free" object: {aName=Test, objects={key2=Nov 23, 2013 1:33:23 AM, key1=1.0}, aExpressions=[Stack, Overflow]}

您可以根据需要使用一种或其他方法。

关于TypeToken,由于泛型擦除,类似这样

  List<Data> list = new Gson().parse(aJsonString, List<Data>.class)

行不通,你必须做类似的事情

  Type listType = new TypeToken<List<Data>>() {}.getType();
  List<Data> list = new Gson().parse(aJsonString, listType.class)

但这种情况实际上适用于当您的 JSON 是一个数组并且您希望将其反序列化为自定义类列表时。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    相关资源
    最近更新 更多