将Json数组映射到Java模型

问题描述 投票:1回答:3

我在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

我出错的原因和原因是什么?

java json gson
3个回答
1
投票

你有非常复杂的JSON有效载荷,其中相同的属性可以有一个JSON objectJSON 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-suitetest-caseList-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);
    }
}

qazxsw poi在运行时需要在给定qazxsw poi的情况下正确反序列化。之后,让我们创建和自定义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

版本2

在使用上述解决方案后,我想出了下面的解串器:

Parsing JSON with GSON, object sometimes contains list sometimes
contains object

我们不需要自定义它。使用Gson uses TypeAdapter or Json Deserializer to convert data from an error list to an empty list - example with TypeAdapter类,我们可以获得元素类型和反序列化内部元素。用法简单:

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

上面的代码也应该适合你。


0
投票

我想你可以用杰克逊。

$Gson$Types

0
投票

在你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); } } 根元素是json对象:

ObjectMapper mapper = new ObjectMapper();
List<ChromeJsonModel> participantJsonList = mapper.readValue(jsonString, new TypeReference<List<ChromeJsonModel>>(){});

更改:

json

至:

{    <---- HERE YOU HAVE "OBJECT"

  "test-run": {
    "duration": 508.56199999999995,
    "result": "Passed",
    ...
   }

}

你可以尝试在那里生成POJO:List<ChromeJsonModel> jsonModelList = (List<ChromeJsonModel>) ... ;

© www.soinside.com 2019 - 2024. All rights reserved.