我在这里有一个复杂的json
我正在尝试在我的模型类“ ChromeJsonModel”中映射它,例如:
Type collectionType = new TypeToken<List<ChromeJsonModel>>(){}.getType(); List<ChromeJsonModel> jsonModelList = (List<ChromeJsonModel>) new Gson().fromJson( jsonPrettyPrintString , collectionType);
但是我收到以下错误。
Expected BEGIN_ARRAY but was BEGIN_OBJECT
我为什么会在哪里出问题?
您拥有非常复杂的JSON有效负载,其中相同的属性可能具有一个JSON object或JSON array多个对象。Gson默认情况下不会处理这种情况,因此我们需要为此类one-or- many属性实现自定义反序列化器。下面我创建了POJO代表您的JSON有效负载的简单模型:
JSON
JSON object
JSON array
Gson
one-or- many
POJO
class TestResponse { @SerializedName("test-run") private TestRun testRun; // other properties, getters, setters, toString } class TestRun { @SerializedName("test-suite") private List<TestSuite> testSuite; // other properties, getters, setters, toString } class TestSuite { private String result; private double duration; @SerializedName("test-suite") private List<TestSuite> testSuites; @SerializedName("test-case") private List<TestCase> testCases; // other properties, getters, setters, toString } class TestCase { private String fullname; // other properties, getters, setters, toString }
如您所见test-suite,它test-case是List-es属性。让我们为这些属性实现自定义反序列化器:
test-suite
test-case
List
class OneOrManyJsonDeserializer<E> implements JsonDeserializer<List<E>> { private final Class<E> clazz; public OneOrManyJsonDeserializer(Class<E> clazz) { this.clazz = clazz; } @Override public List<E> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { if (json instanceof JsonArray) { final JsonArray array = (JsonArray) json; final int size = array.size(); if (size == 0) { return Collections.emptyList(); } final List<E> suites = new ArrayList<>(size); for (int i = 0; i < size; i++) { suites.add(context.deserialize(array.get(i), clazz)); } return suites; } E suite = context.deserialize(json, clazz); return Collections.singletonList(suite); } }
Class<E>在运行时需要正确地反序列化JSON object。之后,让我们创建和自定义Gson实例:
Class<E>
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; import java.io.File; import java.io.FileReader; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class GsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); Type testCaseListType = new TypeToken<List<TestCase>>() {}.getType(); Type testSuiteListType = new TypeToken<List<TestSuite>>() {}.getType(); Gson gson = new GsonBuilder() .registerTypeAdapter(testCaseListType, new OneOrManyJsonDeserializer<>(TestCase.class)) .registerTypeAdapter(testSuiteListType, new OneOrManyJsonDeserializer<>(TestSuite.class)) .setPrettyPrinting() .create(); TestResponse response = gson.fromJson(new FileReader(jsonFile), TestResponse.class); System.out.println(response); } }
如您所见,我们为每种one-to-many类型注册了两个实例。我们需要使用TypeToken来正确映射我们的实例。
one-to-many
TypeToken
经过上述解决方案,我想出了以下反序列化器:
class OneOrManyJsonDeserializer implements JsonDeserializer<List<?>> { @Override public List<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { final Type elementType = $Gson$Types.getCollectionElementType(typeOfT, List.class); if (json instanceof JsonArray) { final JsonArray array = (JsonArray) json; final int size = array.size(); if (size == 0) { return Collections.emptyList(); } final List<?> suites = new ArrayList<>(size); for (int i = 0; i < size; i++) { suites.add(context.deserialize(array.get(i), elementType)); } return suites; } Object suite = context.deserialize(json, elementType); return Collections.singletonList(suite); } }
我们不需要对其进行自定义。使用$Gson$Types类,我们可以获得元素的类型并反序列化内部元素。简单用法:
$Gson$Types
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; import com.google.gson.internal.$Gson$Types; import java.io.File; import java.io.FileReader; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class GsonApp { public static void main(String[] args) throws Exception { File jsonFile = new File("./resource/test.json").getAbsoluteFile(); Gson gson = new GsonBuilder() .registerTypeAdapter(List.class, new OneOrManyJsonDeserializer()) .setPrettyPrinting() .create(); TestResponse response = gson.fromJson(new FileReader(jsonFile), TestResponse.class); System.out.println(response); } }
上面的代码也应该为您工作。