android - 带有额外变量的 gson 数组反序列化

标签 android arrays json arraylist gson

我不确定这是否可能重复,但我找不到类似的问题。

目前,我正在尝试从我公司使用的 API 中检索一个数组。 由于我从 API 检索了所有这些数据,因此我还收到了一条状态消息,其中包含字符串成功或字符串错误。 我正在使用 Gson 和 Retrofit 来检索和反序列化 JSON 数据。

这适用于每个对象,但现在我需要制作一个也是数组的对象。

从 API 检索到的 json 输出。

{
   "0":{
      "first_name":"Menno",
      "avatar":"[avatar here]",
      "updated_at":"2017-04-08 11:17:35",
      "id":"[id here]"
   },
   "1":{
      "first_name":"Team",
      "avatar":"[avatar here]",
      "updated_at":"2017-11-01 11:00:18",
      "id":"[id here]"
   },
   "success":"retrieve_common_connections_success"
}

如您所见,json 以索引数组开始,以成功消息结束。

用于反序列化 JSON 的类。

public class GetCommonConnections extends ArrayList<Connection> {
    public String getSuccess() {
        return success;
    }

    public void setSuccess(String success) {
        this.success = success;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    @SerializedName("success")
    private String success = "";
    @SerializedName("error")
    private String error = "";

}

我也收到错误:D/Error: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

这意味着 gson 期望以数组开头,但它以对象开头。 我对它的工作原理有点迷茫,想知道你们是否有解决方案。

编辑

连接类。

public class Connection {
    private String first_name;
    private String avatar;
    private String updated_at;
    private int id;

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getUpdated_at() {
        return updated_at;
    }

    public void setUpdated_at(String updated_at) {
        this.updated_at = updated_at;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

还有使用的接口(interface)。

public interface IGetCommonConnections {
    @POST(PostInterfaceMain.POST_URL)
    Call<CommonConnections> getCommonConnections(
            @Body PostConnections body
            );
}

调用API的方法

public static void getCommonConnections(int resourceID, final CustomCallbackHandler callback)
    {
        PostConnections body = new PostConnections();
        body.setResourceID(resourceID);
        body.setAction("resource_get_common_connections");

        IGetCommonConnections taskService = ServiceGenerator.createService(IGetCommonConnections.class);
        Call<CommonConnections> call = taskService.getCommonConnections(body);
        call.enqueue(new Callback<CommonConnections>() {
            @Override
            public void onResponse(Call<CommonConnections> call, Response<CommonConnections> response) {
                if (response.isSuccessful()) {
                    Log.d(TAG, "CommonConnections succesfully retrieved!");
                    callback.setArg(response.body());
                    callback.run();
                } else {
                    // error response, no access to resource?
                }
            }

            @Override
            public void onFailure(Call<CommonConnections> call, Throwable t) {
                // something went completely south (like no internet connection)
                Log.d("Error", t.getMessage());
            }
        });
    }

最佳答案

按原样使用 Connection.java

GetCommonConnections.java

public class GetCommonConnections implements JsonDeserializer<GetCommonConnections>, 
JsonSerializer<GetCommonConnections> {

    public TreeMap<Long, Connection> connectionTreeMap;

    public String success;

    public String error;

    @Override
    public GetCommonConnections deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        Gson gson = new Gson();
        GetCommonConnections getCommonConnections = gson.fromJson(json, GetCommonConnections.class);
        getCommonConnections.connectionTreeMap = new TreeMap<>();

        JsonObject jsonObject = json.getAsJsonObject();
        Set<String> keySet = jsonObject.keySet();
        Iterator<String> keyIterator = keySet.iterator();

        while (keyIterator.hasNext()) {

            String key = keyIterator.next();

            if (TextUtils.isDigitsOnly(key)) {

                getCommonConnections.connectionTreeMap.put(Long.valueOf(key),
                        gson.fromJson(jsonObject.get(key), Connection.class));
            }
        }

        return getCommonConnections;
    }

    @Override
    public JsonElement serialize(GetCommonConnections src, Type typeOfSrc, JsonSerializationContext context) {

        Gson gson = new Gson();
        JsonObject jsonObject = new JsonObject();

        Set<Long> longSet = src.connectionTreeMap.keySet();
        Iterator<Long> longIterator = longSet.iterator();

        while (longIterator.hasNext()) {

            Long key = longIterator.next();

            jsonObject.add(String.valueOf(key),
                    gson.toJsonTree(src.connectionTreeMap.get(key)));
        }

        jsonObject.addProperty("success", src.success);
        jsonObject.addProperty("error", src.error);

        return jsonObject;
    }
}

自定义GsonConverterFactory

public GsonConverterFactory createCustomGsonConverterFactory() {

        GsonBuilder gsonBuilder = new GsonBuilder();

        gsonBuilder.registerTypeAdapter(GetCommonConnections.class,
                new GetCommonConnections());

        Gson gson = gsonBuilder.create();

        return GsonConverterFactory.create(gson);
    }

构建改造如下 -

public Retrofit buildRetrofit() {

    return new Retrofit.Builder()
            .baseUrl("your base URL")
            .addConverterFactory(createCustomGsonConverterFactory())
            .build();
}

用于测试 GetCommonConnections JsonDeserializer 和 JsonSerializer 是否有效的代码 -

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String jsonResponseString = "{\n" +
                "   \"0\":{\n" +
                "      \"first_name\":\"Menno\",\n" +
                "      \"avatar\":\"[avatar here]\",\n" +
                "      \"updated_at\":\"2017-04-08 11:17:35\",\n" +
                "      \"id\":101\n" +
                "   },\n" +
                "   \"1\":{\n" +
                "      \"first_name\":\"Team\",\n" +
                "      \"avatar\":\"[avatar here]\",\n" +
                "      \"updated_at\":\"2017-11-01 11:00:18\",\n" +
                "      \"id\":102\n" +
                "   },\n" +
                "   \"success\":\"retrieve_common_connections_success\"\n" +
                "}";

        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(GetCommonConnections.class,
                new GetCommonConnections());
        Gson gson = gsonBuilder.create();

        GetCommonConnections getCommonConnections = gson.fromJson(jsonResponseString, GetCommonConnections.class);

        Log.d("MainActivity", "-> " + gson.toJson(getCommonConnections));
    }
}

还有你这个电话无处不在-

Call<GetCommonConnections>

关于android - 带有额外变量的 gson 数组反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47109731/

相关文章:

sql - 如何在postgres中过滤json的任何键的值

android - 删除 phonegap 中的缓存图像

arrays - 快速使用外部数据库值填充 TableView

javascript - 如何在 JavaScript 中将数字数组拆分为单个数字?

java - 如何在自定义反序列化器Gson中小写JsonElement值?

c++ - 在这种情况下如何让 jsoncpp 抛出异常?

android - 启用 proguard 时不会调用 Serialized 中的 readObject 函数

javascript - 使用 javascript/jQuery 刷新特定 div 内容

android - Appium 显示错误“未知错误 : Chrome version must be >= 31. 0.1650.59\n 即使 Android 移动应用程序中的 chrome 版本更高

java - 将数组中的数据放入 Android View 中