当前位置: 首页 > 面试题库 >

如何使用GSON序列化地图?

龚睿
2023-03-14
问题内容

我想使用GSON将下面的Example类序列化为JSON。

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.LinkedHashMap;

public class Example
{
    private LinkedHashMap<String,Object> General;

    private static final String VERSION="Version";
    private static final String RANGE="Range";
    private static final String START_TIME="Start_Time";
    private static final String END_TIME="End_Time";

    public Example() {
        General = new LinkedHashMap<String,Object>();
        General.put(VERSION, "0.1");

        LinkedHashMap<String,String> Range = new LinkedHashMap<String, String>();
        Range.put(START_TIME, "now");
        Range.put(END_TIME, "never");

        General.put(RANGE, Range);
    }

    public String toJSON() {
        Gson gson = new GsonBuilder().serializeNulls().create();
        return gson.toJson(this);
    }
}

我期望得到以下输出:

{"General":{"Version":"0.1","Range":{"Start_Time":"now","End_Time":"never"}}}

但是调用函数toJSON()返回

{"General":{"Version":"0.1","Range":{}}}

看来GSON无法在Map Range内序列化Map General。这是GSON的限制,还是我在这里做错了?


问题答案:

Nishant的答案之所以起作用,是因为Gson的默认构造函数默认启用了所有东西,否则您将不得不使用GsonBuilder手动启用它们。

从JavaDocs:

使用默认配置构造一个Gson对象。默认配置具有以下设置:

* toJson方法生成的JSON以紧凑形式表示。这意味着将删除所有不需要的空格。您可以使用GsonBuilder.setPrettyPrinting()更改此行为。
* 生成的JSON会忽略所有为空的字段。请注意,由于数组是有序列表,因此数组中的null保持原样。此外,如果字段不为null,但其生成的JSON为空,则保留该字段。您可以通过设置GsonBuilder.serializeNulls()将Gson配置为序列化空值。
* Gson为Enums,Map,java.net.URL,java.net.URI,java.util.Locale,java.util.Date,java.math.BigDecimal和java.math.BigInteger类提供了默认的序列化和反序列化。如果您希望更改默认表示,则可以通过GsonBuilder.registerTypeAdapter(Type,Object)注册类型适配器来进行更改。
* 默认的日期格式与java.text.DateFormat.DEFAULT相同。此格式在序列化过程中忽略日期的毫秒部分。您可以通过调用GsonBuilder.setDateFormat(int)或GsonBuilder.setDateFormat(String)来更改此设置。
* 默认情况下,Gson会忽略com.google.gson.annotations.Expose注释。您可以通过GsonBuilder.excludeFieldsWithoutExposeAnnotation()使Gson仅序列化/反序列化带有此批注的字段。
* 默认情况下,Gson会忽略com.google.gson.annotations.Since注释。您可以允许Gson通过GsonBuilder.setVersion(double)使用此注释。
* 输出Json的默认字段命名策略与Java中的相同。因此,Java类字段versionNumber在Json中将作为“ versionNumber
@”输出。相同的规则也适用于将传入的Json映射到Java类。您可以通过GsonBuilder.setFieldNamingPolicy(FieldNamingPolicy)更改此策略。
* 默认情况下,Gson在进行序列化和反序列化时不考虑瞬态或静态字段。您可以通过GsonBuilder.excludeFieldsWithModifiers(int)更改此行为。



好的,现在我看到了问题所在。如您所料,默认的Map序列化程序不支持嵌套映射。正如您从DefaultTypeAdapters的此源代码片段中看到的(尤其是如果您使用调试器进行调试),由于某种神秘的原因,该变量childGenericType被设置为类型java.lang.Object,因此永远不会分析该值的运行时类型。

我猜有两种解决方案:

  1. 实现自己的Map序列化器/反序列化器
  2. 使用更复杂的方法版本,如下所示:
    public String toJSON(){
    final Gson gson = new Gson();
    final JsonElement jsonTree = gson.toJsonTree(General, Map.class);
    final JsonObject jsonObject = new JsonObject();
    jsonObject.add("General", jsonTree);
    return jsonObject.toString();
    

    }



 类似资料:
  • 问题内容: 我想使用GSON将下面的Example类序列化为JSON。 我期望得到以下输出: 但是调用函数返回 看来GSON无法在Map 内序列化Map 。这是GSON的限制,还是我在这里做错了? 问题答案: Nishant的答案之所以起作用,是因为Gson的默认构造函数默认启用所有类型的东西,否则您将不得不使用GsonBuilder手动启用它们。 从JavaDocs: 使用默认配置构造一个Gso

  • 问题内容: 我在尝试序列化包含 即使我写了: 并应用: 我仍然无法序列化此类: Stacktrace :(在pastebin上完整) 有什么办法吗? 问题答案: 您的问题是那是一个。假设您使用它将在Windows PC上创建类似的实例。现在,您必须告诉GSON如何反序列化此类型: 您可以使用的另一种方法是: typeHierarchyAdapter的目的是在您希望为类型的所有子类型使用相同的表示形

  • 我有一个具有以下属性的对象。 该对象位于库中,我不希望仅为了序列化目的而修改它,并且希望避免创建另一个DTO的成本。 我如何序列化/反序列化可选属性?可选没有默认构造函数(两个apache公共对都没有),但我不能使用InstanceCreator,也不真正了解如何创建一个TypeAdapter,它只会将序列化委托给底层的可选内容。

  • 在我的servlet中,我有以下代码: 响应从 Ajax 返回,代码如下: 当我运行代码时,我仍然收到以下错误(来自 ajax): 我还尝试显示序列化对象<code>List 我收到此错误: 请帮帮忙! 编辑:这个问题的最终解决方案

  • 问题内容: 我使用了很多不可变的集合,并且很好奇如何使用Gson反序列化它们。由于没有人回答,而且我自己找到了解决方案,因此我正在简化问题并提出自己的答案。 我有两个问题: 如何为所有人编写一个作品? 如何全部注册? 问题答案: 更新:有https://github.com/acebaggins/gson- serializers ,其中涵盖了许多番石榴集合: 如何编写适用于所有Immutable

  • 问题内容: 我想使用套接字(在开发远程PC时)从Android客户端向Java服务器发送2个对象。 当然我知道上面的方法是行不通的,因为它可以提供。因此,现在我想知道如何使用Gson库对对象进行序列化和反序列化。提前致谢。 问题答案: gson可以在任何平台上与Java一起使用-不仅限于Android。 使用gson序列化单个对象: 使用gson反序列化为单个对象。 从示例中可以看到,gson非常