如何在 Java 模块中使用 GSON

问题描述

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

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

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

我试图请求一个用户列表,响应被放在一个只在客户端模块中定义的类中,如下所示:

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

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

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

这是字符串 json 值的示例:

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

对我来说一切都很好,但我收到了这个异常,这似乎表明问题是 User 类位于与我尝试解析它的模块不同的模块中?

java.lang.classCastException: class com.google.gson.internal.LinkedTreeMap 无法转换为 class model.User(com.google.gson.internal.LinkedTreeMap 位于加载器“app”的模块 [email protected] 中;模型.用户在加载器'app'的模块inventoryCommon中)

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

PS 我的代码基于我在本文中阅读的内容tutorial

解决方法

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

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

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

function startsWithInteger(a,b) {
  //get which power of 10 each number is in
  const exponentA = Math.floor(Math.log10(a));
  const exponentB = Math.floor(Math.log10(b));
  
  //get magnitude to compare the two. Cap at 1 (10 ** 0)
  let comparativeMagnitude = 10 ** Math.max((exponentA - exponentB),0);

  //get the "start of" of `a` with an intiger division
  //by the common power of 10 to get the same number of digits 
  const startA = Math.floor(a / comparativeMagnitude);
  
  return startA === b;
}

console.log(startsWithInteger(567,2));    //false
console.log(startsWithInteger(267,2));    //true
console.log(startsWithInteger(567,50));   //false
console.log(startsWithInteger(567,56));   //true
console.log(startsWithInteger(567,5670)); //false
console.log(startsWithInteger(567,567));  //true