如何使用Gson将JSON映射转换为自定义Java列表?
给出这样的JSON映射:
{
"category1": [],
"category2": ["item1"],
"category3": ["item1", "item2"]
}
我想将其转换为类别的Java ArrayList(而不是Map),如下所示:
class Category {
final String categoryName;
final ArrayList<String> items;
public Category(String categoryName, ArrayList<String> items) {
this.categoryName = categoryName;
this.items = items;
}
}
ArrayList<Category> data = new ArrayList<>();
所以我希望data
看起来像这样:
for (Category c: data) {
System.out.println(c.categoryName + ", " + c.items);
}
/**
Expected data =
category1, empty list [] or null
category2, [item1]
category2, [item1, item2]
**/
我试过使用Gson库:
应用/构建。格拉德尔:
dependencies {
...
implementation 'com.google.code.gson:gson:2.8.6'
}
JSONConvertest。java
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonParser;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import org.junit.Test;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class JsonConverterTest {
@Test
public void gsonMapToListTest() {
String json = "{\"category1\": [],\"category2\": [\"item1\"],\"category3\": [\"item1\", \"item2\"]}";
class Category {
final String categoryName;
final ArrayList<String> items;
public Category(String categoryName, ArrayList<String> items) {
this.categoryName = categoryName;
this.items = items;
}
}
ArrayList<Category> expectedData = new ArrayList<>();
expectedData.add(new Category("category1", new ArrayList<String>()));
expectedData.add(new Category("category2", new ArrayList<>(Arrays.asList("item1"))));
expectedData.add(new Category("category2", new ArrayList<>(Arrays.asList("item1", "item2"))));
System.out.println("Expected Data:");
for (Category c: expectedData) {
System.out.println(c.categoryName + ", " + c.items);
}
// This works, but it returns a Map instead of a List
LinkedTreeMap<String, ArrayList<String>> dataMap = new Gson().fromJson(json, LinkedTreeMap.class);
System.out.println("\n data as Map = " + dataMap);
// This causes "IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $"
Type listOfCategoriesType = new TypeToken<ArrayList<Category>>() {}.getType();
ArrayList<Category> data = new Gson().fromJson(json, listOfCategoriesType); // IllegalStateException here
assertThat(data, is(expectedData));
// This causes "java.lang.IllegalStateException: Not a JSON Array: {...}"
JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray(); // IllegalStateException here
data = new Gson().fromJson(jsonArray, listOfCategoriesType);
assertThat(data, is(expectedData));
}
}
使用指南https://www.baeldung.com/gson-list和https://futurestud.io/tutorials/gson-mapping-of-maps,我只能将JSON映射转换为Java映射。但如果我试图将JSON映射转换为Java列表,就会得到一个非法状态异常:
Type listOfCategoriesType = new TypeToken<ArrayList<Category>>() {}.getType();
ArrayList<Category> data = new Gson().fromJson(json, listOfCategoriesType); // IllegalStateException
或者
JsonArray jsonArray = JsonParser.parseString(json).getAsJsonArray(); // IllegalStateException
ArrayList<Category> data2 = new Gson().fromJson(jsonArray, listOfCategoriesType);
那么,在Gson中,根据上面的单元测试gsonMapToListTest()
,将Json映射转换为Java列表的正确方法是什么呢
# 1 楼答案
这不是最简单的方法,但Gson允许实现这样的类型适配器,这样您就可以在结果对象中反序列化JSON,而无需中间集合
以下测试为绿色:
# 2 楼答案
最简单的方法是简单地解析成
Map
,然后将Map
转换成List<Category>
另一种方法是编写自己的^{} ,或者使用另一个JSON库