【发布时间】:2021-06-05 04:19:45
【问题描述】:
给定一个像这样的 JSON 映射:
{
"category1": [],
"category2": ["item1"],
"category3": ["item1", "item2"]
}
我想将其转换为 Java ArrayList of Categories(不是 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 库:
app/build.gradle:
dependencies {
...
implementation 'com.google.code.gson:gson:2.8.6'
}
JsonConverterTest.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 列表,则会收到 IllegalStateException:
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);
那么根据上面的单元测试gsonMapToListTest(),Gson 中将 Json Map 转换为 Java 列表的正确方法是什么?
【问题讨论】:
-
不能改变Json格式吗?
-
@B.M 很遗憾,无法更改 Json 格式。这是外部 API 给出的规范。
标签: java json arraylist gson json-deserialization