Json映射到Java映射

时间:2019-10-07 14:30:50

标签: java dictionary gson

我有以下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结构是否错误,或者有更简单的方法来映射它?

4 个答案:

答案 0 :(得分:0)

尝试读取此json文件

df=pd.DataFrame({'date':['20190606','20190610','20190708','20190805','20190909','20190930'],'number':[3,5,4,1,0,0], 'avg_last_2m':[None,3,4,4,1,0.5]})

df["date"]=pd.to_datetime(df.date, format="%Y%m%d")
df["date_minus_2m"]=df["date"]-pd.DateOffset(months=2)

def avg_2m (row):
    avg_2m = df[(df.date>=row["date_minus_2m"])&(df.date<=row["date"])]["number"].mean()
    return avg_2m
df["avg_2m"]=df.apply(avg_2m, axis=1)

答案 1 :(得分:0)

上面的json是JsonObject的集合,例如列表或数组,因此只需将其解析为List个对象的Map

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

答案 2 :(得分:0)

您的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);
    }
}

答案 3 :(得分:0)

您的输入是一个带有两个对象的json数组。但是,目标变量“类型”是对象类型,而不是“对象数组”。简单来说,地图无法存储 数组。

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

yourJson -> [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的解决方案,因此可以确定存在比上述更干净的解决方案)。在这里,我们将使用ObjectMapper

中的com.fasterxml.jackson.databind.ObjectMapper
ObjectMapper om = new ObjectMapper();
List<Map.Entry<String, Category>> listx = om.readValue(text, ArrayList.class);

如果打印listx。您可以看到以下内容(覆盖Category类的toString()):

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

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

现在,如果您需要地图,那么我将作为练习,教您如何将Map.Entry列表转换为Map实现。

PS .:这里是第一个长答案。如有任何错误,我们深表歉意。