为了账号安全,请及时绑定邮箱和手机立即绑定

将 Json 数组映射到 Java 模型

将 Json 数组映射到 Java 模型

慕婉清6462132 2022-08-03 10:46:05
我有一个复杂的json,就像在这里一样我正在尝试在我的模型类“ChromeJsonModel”中映射它,例如:Type collectionType = new TypeToken<List<ChromeJsonModel>>(){}.getType(); List<ChromeJsonModel> jsonModelList = (List<ChromeJsonModel>) new Gson().fromJson( jsonPrettyPrintString , collectionType);Bu t 我收到以下错误。Expected BEGIN_ARRAY but was BEGIN_OBJECT我为什么以及哪里出错的原因是什么?
查看完整描述

3 回答

?
慕运维8079593

TA贡献1876条经验 获得超5个赞

您有非常复杂的有效负载,其中同一属性可以有一个或一个对象。 默认情况下不处理这种情况,我们需要为此类属性实现自定义 deserialiser。下面我创建了表示您的有效负载的简单模型:JSONJSON objectJSON arrayGsonone-or-manyPOJOJSON


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

}

如您所见,是 -es 属性。让我们为这些属性实现自定义 deserialiser:test-suitetest-caseList


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 objectGson


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-manyTypeToken

版本 2

在玩了上面的解决方案之后,我想出了下面的deserialiser:


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

    }

}

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


查看完整回答
反对 回复 2022-08-03
?
森栏

TA贡献1810条经验 获得超5个赞

我认为你可以使用杰克逊。

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


查看完整回答
反对 回复 2022-08-03
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

在你的根元素是 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/


查看完整回答
反对 回复 2022-08-03
  • 3 回答
  • 0 关注
  • 145 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信