如何将 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());
}
}
我有三个模块,客户端、服务器和公共模块。公共模块完全由 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());
}
}