【问题标题】:How to serialize/deserialize Java Object[] correctly?如何正确序列化/反序列化 Java Object[]?
【发布时间】:2018-10-30 11:24:58
【问题描述】:

我正在写一个 rpc 框架,但是遇到了关于序列化的问题。

你知道在客户端和服务器之间翻译请求,我应该有一个这样的请求类:

class Request {
    // target service class
    private Class<?> targetService;
    // target service method
    private String targetMethod;
    // target method param types
    private Class<?>[] targetParamTypes;
    // the params
    private Object[] targetParams;
    // getters & setters & contructors
}

但是:

  1. 对于targetParams字段,如果我使用Gson作为序列化工具,如果我将POJOs放入targetParams,它会得到com.google.gson.internal.LinkedTreeMap cannot be cast to the.packages.to.MyClass错误,对于一般问题。

  2. 对于int 类,Gson 总是将其解析为Double,所以我不能使用targetParamTypes[i].cast(targetParams[i]) 强制将其强制转换为整数(双精度不能转换为整数),它很烂...

那么有人有解决问题的方法吗?如何使序列化/反序列化步骤快速准确?或者有什么推荐的工具?

我试过了:

  • Gson,解决之前的问题
  • Kyro,编解码器系统很烂,我不知道如何序列化/反序列化 HashMap...
  • protostuff,嗯,它不支持 Java 9+,我的环境是 Java 11,糟透了!

有什么建议吗?

【问题讨论】:

  • 不就是实现Serializable类那么简单吗?

标签: java json serialization protocol-buffers rpc


【解决方案1】:

您可以查看Jackson。 Jackson 的ObjectMapper 应该能够从您的Request 对象转换为String,反之亦然。

编辑:添加示例

请求实体:

class Request {

    private Class<?> targetService;
    private String targetMethod;
    private Class<?>[] targetParamTypes;
    private Object[] targetParams;

    // needed by Jackson
    private Request(){

    }

    public Request(Class<?> targetService, 
                   String targetMethod, 
                   Class<?>[] targetParamTypes, 
                   Object[] targetParams) {
        this.targetService = targetService;
        this.targetMethod = targetMethod;
        this.targetParamTypes = targetParamTypes;
        this.targetParams = targetParams;
    }

    // getters and setters, needed by Jackson

}

序列化/反序列化示例:

public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();

    Request req = new Request(String.class, "test", new Class[] {String.class}, new Object[] {"Test"});
    String serialized = mapper.writeValueAsString(req);
    System.out.println(serialized);

    req = mapper.readValue(serialized, Request.class);
    System.out.println(req);
}

【讨论】:

  • 不行,我使用 Serializable[] 时出错:Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.io.Serializable`...顺便说一句,你能分享一段示例代码来序列化/反序列化 Request 类吗?
  • @UkonnRa 添加了示例。不要将targetParams 重构为Serializable,但要确保您存储在那里的对象确实是可序列化的。
  • 哇,它有效!多谢!但是为什么 Gson 不能使用类似的代码(使用 toJson,fromJson)...
  • 欢迎。尽管方法签名有些相似,但 Gson API 使用不同的实现来序列化/反序列化对象。我没用过Gson,所以不知道具体为什么会失败。
  • 不,它失败了......我发现类型是错误:var obj = new RequestWrapper(UUID.randomUUID().toString(), System.currentTimeMillis(), HelloWorldService.class, "getExp", new Class[]{MessageRequest.class}, new Object[]{new MessageRequest(UUID.randomUUID().toString(), 2, 10)}); 当你序列化它并反序列化它时,newObj.getParams()[0] 将是一个java.util.LinkedHashMap 而不是一个@ 987654333@
【解决方案2】:

使用 JSON 代替 GSON 并在你的 pojo 中实现 Serializable

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2022-01-02
    • 1970-01-01
    相关资源
    最近更新 更多