【问题标题】:Json map into java mapJson映射成java映射
【发布时间】:2019-10-07 14:30:50
【问题描述】:

我有以下 json 文件

[{
        "en": {
            "key1": "Ap",
            "key2": "ap2"
        }
    },

    {
        "ar": {
            "key1": "Ap",
            "key2": "ap2"
        }
    }
]

我想在 Java 中创建一个 Map,例如键是语言(如 en 或 ar),值是对象。像这样。

public class Category {
    private String key1;
    private String key2;
}

    Type type = new TypeToken<Map<String, Category>>() {}.getType();
    Gson gson = new Gson();

    InputStream in = MyClass.class.getResourceAsStream("/categories.json");
    String text = IOUtils.toString(in, StandardCharsets.UTF_8);
    Map<String, Category> map = gson.fromJson(text, type);

但是当我运行这段代码时,我得到了错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 3 path $[0]

我的 Json 结构是错误的还是有更简单的方法来映射它?

【问题讨论】:

    标签: java dictionary gson


    【解决方案1】:

    尝试读取这个 json 文件

     {
      "ar": {
        "key1": "Ap",
        "key2": "ap2"
      },
      "en": {
        "key1": "Ap",
        "key2": "ap2"
      }
    }
    

    【讨论】:

      【解决方案2】:

      上面的 json 是 JsonObject 之类的列表或数组的集合,所以只需将其解析为 ListList 对象

      Type type = new TypeToken<List<Map<String, Category>>>() {}.getType();
      

      【讨论】:

        【解决方案3】:

        您的 json 是地图列表,而不仅仅是地图。所以你必须将它添加到声明的类型中。

        试试这个:

        import com.google.gson.Gson;
        import com.google.gson.reflect.TypeToken;
        
        import java.lang.reflect.Type;
        import java.util.List;
        import java.util.Map;
        
        public class Category {
            private String key1;
            private String key2;
        
            @Override
            public String toString() {
                return "Category{" +
                        "key1='" + key1 + '\'' +
                        ", key2='" + key2 + '\'' +
                        '}';
            }
        
            public static void main(String[] args) {
        
                String json = "[{\n" +
                        "        \"en\": {\n" +
                        "            \"key1\": \"Ap\",\n" +
                        "            \"key2\": \"ap2\"\n" +
                        "        }\n" +
                        "    },\n" +
                        "\n" +
                        "    {\n" +
                        "        \"ar\": {\n" +
                        "            \"key1\": \"Ap\",\n" +
                        "            \"key2\": \"ap2\"\n" +
                        "        }\n" +
                        "    }\n" +
                        "]";
        
                Type type = new TypeToken<List<Map<String, Category>>>() {}.getType();
                Gson gson = new Gson();
        
                List<Map<String, Category>> maps = gson.fromJson(json, type);
                System.out.println(maps);
            }
        }
        

        【讨论】:

          【解决方案4】:

          您的输入是一个包含两个对象的 json 数组。但是,您的目标变量“类型”是对象类型,而不是“对象数组”。简单来说,Map 不能存储 数组。

          让我们采取一种更简单的方法来解决这个问题(不是推荐的方法)。如果我们手动将地图转换为地图数组,则如下所示:

          yourJson -&gt; [Map1(en,category1(Ap,ap2)),Map2(en,category2(Ap,ap2))]

          即地图数组

          所以在 java 中相当于:

          Type typeOfT2 = new TypeToken<ArrayList<HashMap<String, Category>>>() {}.getType();
          List<HashMap<String, Category>> list = gson.fromJson(text, typeOfT2);
          

          我们得到了我们想要的,但是有更好的方法来做到这一点。为此,我们需要 Jackson 而不是 Gson。(有人可能会添加基于 Gson 的解决方案,很确定存在比上述更清洁的解决方案)。这里我们将使用来自com.fasterxml.jackson.databind.ObjectMapperObjectMapper

          ObjectMapper om = new ObjectMapper();
          List<Map.Entry<String, Category>> listx = om.readValue(text, ArrayList.class);
          

          如果您打印listx。你可以看到这个(覆盖类别类的toString()):

          [{en={key1=Ap, key2=ap2}}, {ar={key1=Ap, key2=ap2}}]

          listx 是最准确的 json 表示,而不是 Map。

          现在,如果您需要地图,我将把它作为练习留给您,了解如何将 Map.Entry 列表转换为 Map 实现。

          PS.:这里的第一个长答案。对任何错误表示歉意。

          【讨论】:

            猜你喜欢
            • 2017-05-02
            • 1970-01-01
            • 2018-06-18
            • 1970-01-01
            • 1970-01-01
            • 2019-05-27
            • 2017-01-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多