【问题标题】:Parsing JSON maps / dictionaries with Gson?用 Gson 解析 JSON 地图/字典?
【发布时间】:2023-03-10 04:26:01
【问题描述】:

我需要解析如下所示的 JSON 响应:

{"key1": "value1", 
 "key2": "value2", 
 "key3": 
    {"childKey1": "childValue1", 
     "childKey2": "childValue2", 
     "childKey3": "childValue3" }
}

class Egg { 
    @SerializedName("key1")
    private String mKey1;

    @SerializedName("key2")
    private String mKey2;

    @SerializedName("key3")
    // ???
}

我正在阅读 Gson 文档,但无法弄清楚如何将字典正确反序列化为 Map。

【问题讨论】:

    标签: java json dictionary map gson


    【解决方案1】:

    Gson 可以轻松地将带有名称:值对的 JSON 对象反序列化为 Java Map

    以下是使用原始问题中的 JSON 的示例。 (此示例还演示了使用FieldNamingStrategy 来避免为每个字段指定序列化名称,前提是字段到元素的名称映射是一致的。)

    import java.io.FileReader;
    import java.lang.reflect.Field;
    import java.util.Map;
    
    import com.google.gson.FieldNamingStrategy;
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    
    public class Foo
    {
      public static void main(String[] args) throws Exception
      {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.setFieldNamingStrategy(new MyFieldNamingStrategy());
        Gson gson = gsonBuilder.create();
        Egg egg = gson.fromJson(new FileReader("input.json"), Egg.class);
        System.out.println(gson.toJson(egg));
      }
    }
    
    class Egg
    {
      private String mKey1;
      private String mKey2;
      private Map<String, String> mKey3;
    }
    
    class MyFieldNamingStrategy implements FieldNamingStrategy
    {
      //Translates the Java field name into its JSON element name representation.
      @Override
      public String translateName(Field field)
      {
        String name = field.getName();
        char newFirstChar = Character.toLowerCase(name.charAt(1));
        return newFirstChar + name.substring(2);
      }
    }
    

    【讨论】:

    • 在这种情况下,您将如何在指定序列化名称的同时实现 Map?
    • 我不确定你在问什么。序列化名称是什么?我发布的示例使用自定义 FieldNamingStrategy 来指定 JSON 元素的序列化名称:它们与 Java 字段名称相同,已更改为没有开始的“m”并更改为 Java 字段名称的第二个字符是小写并用作 JSON 元素名称的第一个字符。
    • 哦,我明白了。这就说得通了。但是如何定义 get/set 方法来访问 childKey1、childKey2 和 childKey3?
    • 我不确定你在问什么。这些是地图中的键。您是否在询问如何获取地图中的所有键?为什么要为 Map 键设置一个 setter 方法?它会做什么?您是否可能实际上并不想要 Java 端的 Map,而是按照 Zuljin 建议的方式拥有一个对象?
    • 出于某种原因,我认为您是在建议我仍然使用子类,但它实现了 Map。我明白了,它创建了一个 Map 属性,然后我可以实现自己的 get 方法,这些方法基本上只是从 Map 中获取相应键的值。我需要能够单独获取这些属性,所以我需要公共访问权限。
    【解决方案2】:

    据我所知,您应该为每个 json 对象创建单独的类。 试试这样的:

    class Key { 
        @SerializedName("childKey1")
        private String mchildKey1;
    
        @SerializedName("childKey2")
        private String mchildKey2;
    
        @SerializedName("childKey3")
        private String mchildKey3;
    }
    
    class Egg { 
        @SerializedName("key1")
        private String mKey1;
    
        @SerializedName("key2")
        private String mKey2;
    
        @SerializedName("key3")
        private Key mKey3;
    }
    

    如果这不是您所期望的,您可以编写自己的序列化/反序列化适配器。

    【讨论】:

    • 我将研究定制的适配器。谢谢。
    • 请注意,无需实现自定义反序列化器即可从具有名称:值对的 JSON 对象反序列化为简单的 Map。我在这个问题的另一个答案中发布了一个相关示例。
    猜你喜欢
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多