我在here中有一个复杂的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
我为什么会在哪里出问题?
答案 0 :(得分:1)
您有非常复杂的JSON
有效负载,其中相同的属性可能具有一个JSON object
或JSON array
个对象。 Gson
默认情况下不处理这种情况,我们需要为这种one-or-many
属性实现自定义反序列化器。下面,我创建了一个简单的POJO
模型来表示您的JSON
有效负载:
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属性。让我们为这些属性实现自定义反序列化器:
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
实例:
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
来正确映射实例。
另请参阅:
在使用上述解决方案后,我想到了以下反序列化器:
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
类,我们可以获取元素的类型并反序列化内部元素。简单用法:
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);
}
}
上面的代码也应该对您有用。
答案 1 :(得分:0)
我认为您可以使用杰克逊。
ObjectMapper mapper = new ObjectMapper();
List<ChromeJsonModel> participantJsonList = mapper.readValue(jsonString, new TypeReference<List<ChromeJsonModel>>(){});
答案 2 :(得分:0)
在您json
中,根元素是json对象:
{ <---- HERE YOU HAVE "OBJECT"
"test-run": {
"duration": 508.56199999999995,
"result": "Passed",
...
}
}
更改:
List<ChromeJsonModel> jsonModelList = (List<ChromeJsonModel>) ... ;
收件人:
ChromeJsonModel jsonModelList = (ChromeJsonModel) ... ;
您可以尝试在其中生成POJO: http://pojo.sodhanalibrary.com/