当前位置: 首页 > 面试题库 >

将Gson与接口类型一起使用

徐子石
2023-03-14
问题内容

我正在处理一些服务器代码,其中客户端以JSON形式发送请求。我的问题是,有许多可能的请求,每个请求的实现细节都不尽相同。因此,我想使用一个Request接口,它定义为:

public interface Request {
    Response process ( );
}

从那里,我在名为LoginRequest如下的类中实现了接口:

public class LoginRequest implements Request {
    private String type = "LOGIN";
    private String username;
    private String password;

    public LoginRequest(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * This method is what actually runs the login process, returning an
     * appropriate response depending on the outcome of the process.
     */
    @Override
    public Response process() {
        // TODO: Authenticate the user - Does username/password combo exist
        // TODO: If the user details are ok, create the Player and add to list of available players
        // TODO: Return a response indicating success or failure of the authentication
        return null;
    }

    @Override
    public String toString() {
        return "LoginRequest [type=" + type + ", username=" + username
            + ", password=" + password + "]";
    }
}

为了使用JSON,我创建了一个GsonBuilder实例并注册了一个InstanceCreator,如下所示:

public class LoginRequestCreator implements InstanceCreator<LoginRequest> {
    @Override
    public LoginRequest createInstance(Type arg0) {
        return new LoginRequest("username", "password");
    }
}

然后,如下面的代码片段所示,我使用了它:

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(LoginRequest.class, new LoginRequestCreator());
Gson parser = builder.create();
Request request = parser.fromJson(completeInput, LoginRequest.class);
System.out.println(request);

我得到了预期的输出。

我希望做的是用Request request = parser.fromJson(completeInput, LoginRequest.class);类似于以下内容的内容替换该行,Request request = parser.fromJson(completeInput, Request.class);但是这样做是行不通的,因为这Request是一个接口。

我希望我Gson根据收到的JSON返回适当的请求类型。

我传递给服务器的JSON示例如下所示:

{
    "type":"LOGIN",
    "username":"someuser",
    "password":"somepass"
}

重申一下,我正在寻找一种方法来解析来自客户端的请求(在JSON中)并返回实现该Request接口的类的对象


问题答案:

假设您可能拥有的不同的JSON请求彼此之间并没有太大不同,我建议采用一种不同的html" target="_blank">方法,我认为这种方法更为简单。

假设您有以下3个不同的JSON请求:

{
    "type":"LOGIN",
    "username":"someuser",
    "password":"somepass"
}
////////////////////////////////
{
    "type":"SOMEREQUEST",
    "param1":"someValue",
    "param2":"someValue"
}
////////////////////////////////
{
    "type":"OTHERREQUEST",
    "param3":"someValue"
}

Gson允许您使用一个类来 包装 所有可能的响应,如下所示:

public class Request { 
  @SerializedName("type")   
  private String type;
  @SerializedName("username")
  private String username;
  @SerializedName("password")
  private String password;
  @SerializedName("param1")
  private String param1;
  @SerializedName("param2")
  private String param2;
  @SerializedName("param3")
  private String param3;
  //getters & setters
}

通过使用批注@SerializedName,当Gson尝试解析JSON请求时,它会针对该类中的每个命名属性查找JSON请求中是否存在同名字段。如果没有此类字段,则将类中的属性设置为null

这样,您可以仅使用您的Request类来解析许多不同的JSON响应,如下所示:

Gson gson = new Gson();
Request request = gson.fromJson(jsonString, Request.class);

将JSON请求解析到您的类之后,就可以将数据从 wrap 类传输到具体XxxxRequest对象,例如:

switch (request.getType()) {
  case "LOGIN":
    LoginRequest req = new LoginRequest(request.getUsername(), request.getPassword());
    break;
  case "SOMEREQUEST":
    SomeRequest req = new SomeRequest(request.getParam1(), request.getParam2());
    break;
  case "OTHERREQUEST":
    OtherRequest req = new OtherRequest(request.getParam3());
    break;
}

请注意,如果您有许多不同的JSON请求并且这些请求彼此之间非常不同,则此方法会变得更加乏味,但是即使如此,我仍然认为这是一种很好且非常简单的方法…



 类似资料:
  • 问题内容: 我正在尝试创建一个通用类以与Google Gson一起使用。我已经创建了课程。此类具有以下方法: 目标是该方法应该能够与我设置了GsonJsonConverterImplementation的任何Type一起使用。不幸的是,它不起作用,也不能代替T 使用。我确信问题是由于我对Java泛型类型缺乏理解而引起的。在Gson上使用泛型的正确方法是什么? 使用Kris的答案进行 编辑,我认为这

  • 无法从自定义类获取泛型类型列表(Turns): 它说:

  • 问题内容: 如何将Go程序与C库接口? 我一直在浏览Go的源代码,但我仍然没有弄清楚。如果有人已经这样做了,请分享一下吗? 更新: 感谢@fserb,我从Go来源发布了一些文档: Cgo支持创建调用C代码的Go包。 用法:cgo [编译器选项] file.go 调用gcc编译软件包的C部分时,编译器选项将通过未解释的传递。 输入file.go是一个语法上有效的Go源文件,该文件导入伪包“ C”,然

  • 问题内容: 我的包中有一个结构,上面有耗时的方法,通过工厂函数进行构造也很耗时。因此,在依赖于该其他结构的包中,我希望能够在创建后使用伪造的工厂函数和伪造的结构对其进行测试。由于结构是通过工厂函数构造的,因此我想伪造工厂函数,并在测试期间将替代工厂函数传递给我的结构。 昂贵的包装的一个例子是: 我的主包装使用以下代码: 但是,此代码抱怨以下错误: 。\ main.go:6:不能在字段值中使用昂贵的

  • 这些语句(接口vs类型)有什么区别?