如何将 GSON 与 Java 个模块一起使用

How to use GSON with Java modules

我有三个模块,客户端、服务器和公共模块。公共模块完全由 POJO 模型组成。

所以在公共模块中我有一个这样定义的模型(简化),注意 BaseModel 是一个 class 包含公共审计元素,如创建日期时间等,你应该能够排除它:

package model;

public class User extends BaseModel
{
    private String user, user_id;
    
    public String getUser() {       return user;    }
    public void setUser(String user)    {       this.user = user;   }
    public String getUser_id()  {       return user_id; }
    public void setUser_id(String user_id)  {       this.user_id = user_id; }
}

我正在尝试请求用户列表,响应放在 class 中,仅在客户端模块中定义,如下所示:

package control.model;

import java.util.List;

public class Response<T>
{
    private String status;
    private List<T> response;

    public String getStatus()   {       return status;  }
    public void setStatus(String status)    {       this.status = status;   }
    public List<T> getResponse()    {       return response;    }
    public void setResponse(List<T> list)   {       this.response = list;   }
}

服务器模块创建 JSON 响应,如下所示:

private static String RESP = "{\"status\":\"%s\", \"response\":%s}";

List<User> users = get from database in the server module.
String resp = String.format(RESP, "PASS", new Gson().toJson(users));

common 的模块定义如下:

module inventoryCommon
{
    requires transitive javafx.base;
    exports model;
    opens model to gson;
}

客户端的模块定义如下:

module fileManager
{
    requires transitive java.sql;
    requires transitive javafx.graphics;
    requires transitive javafx.controls;
    
    requires org.apache.logging.log4j;
    requires org.apache.logging.log4j.core;
    requires inventoryCommon;
    
    requires gson;
    requires transitive Java.WebSocket;
    
    exports control;
    
    exports ui to javafx.graphics;
    
    opens control.model to gson;
}

在我的客户端 class 中(也在客户端模块中)我尝试像这样解析响应:

Response<User> response = new Gson().fromJson(json, Response.class);

这里是字符串 json 值的示例:

{"status":"PASS", "response":[{"user":"Me","user_id":"ME123"}, {"user":"You","user_id":"YOU456"}]}

我觉得一切都很好,但我收到了这个异常,这似乎表明问题是 class 用户与我尝试解析它的模块位于不同的模块中?

java.lang.ClassCastException: class com.google.gson.internal.LinkedTreeMap 无法转换为 class model.User (com.google.gson.internal.LinkedTreeMap 在 loader [ 的模块 gson@2.4 中=43=]; model.User 在加载程序 'app')

的模块 inventoryCommon 中

如果您需要更多详细信息,请告诉我。

PS 我的代码是基于我在这篇文章中读到的内容: tutorial

GSON 需要更多它无法从您使用的语法中获取的类型信息。它使用 TypeToken 将通用信息提取到可用于帮助实例化 Response POJO 结构的内容中。

我仅使用 3 classes(响应、用户和一个 class 来测试反序列化,TestModel)成功地在我这边复制了你的问题,并看到了 LinkedTreeMaps(GSON 最接近的比喻在没有足够的类型信息来创建复杂对象时创建类型)。

通过添加 TypeToken 定义,我能够将其反序列化为您的 User 对象。这是我编写的修复它的示例测试。

package control.model;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class TestModel {

    public static void main(String[] args) {

        String json = "{\"status\":\"PASS\", \"response\":[{\"user\":\"Me\",\"user_id\":\"ME123\"}, {\"user\":\"You\",\"user_id\":\"YOU456\"}]}";

        TypeToken<Response<User>> typeToken = new TypeToken<Response<User>>() {} ;
        Response<User> response = new Gson().fromJson(json, typeToken.getType());

        // Run this in DEBUG mode and put a breakpoint in to look at the type of object in "response.getResponse()". Should be an array of USER now, not LinkedTreeMaps...
        System.out.println("RESPONSE: " + response.getStatus());
        System.out.println("RESPONSE: " + response.getResponse());
    }

}