---
# System prepended metadata

title: sui4j和sui-java-sdk合并讨论

---

# sui4j和sui-java-sdk合并讨论

## 差异对比

| 模块 | Sui4j | sui-java-sdk |探讨|
| -------- | -------- | -------- |--------| 
| build tool   | gradle     | maven     | 两种工具都很常见，目前sui4j增加了checkstyle,spotless,jacoco等提高代码风格，质量的工具插件，合并时可能会有不少代码不符合风格需要改动，但是不难|
| json-rpc   | 基于OkHttp自己实现     | 复制的https://github.com/starcoinorg/starcoin-java/tree/main/src/main/java代码     |此处如果作为SDK，个人觉得自己实现更好点，减少不必要的外部依赖；因为这块底层实现不同，存在合并问题|
| json   | 通过接口隐藏了实际使用的序列化库（目前使用Gson）     | 直接使用Jackson     |此作为SDK我觉得这里不直接把具体的序列化库暴露给用户比较好；因为这块底层使用库也不同，存在合并问题|
| websocket    | 基于OkHttp自己实现     | 直接使用web3j的方法     |同json-rpc个人觉得自己实现更好，减少不必要的外部依赖；这块实现不同，存在合并问题|
| 接口设计    | 异步接口     | 同步接口    |这块存在合并问题|

## 构建工具

使用 Gradle 还是 Maven 我感觉问题都不大，因为我们做的东西是项目结构上比较简单的“类库”项目，不需要太复杂的构建管理。

## HTTP Client

其实我从 Starcoin Java SDK 移过来的 JSON RPC Client 的代码实现内部也是使用了 okHttp 的。只是在 okHttp 至上做了一些封装。

## JSON 库

如果不是实在没有办法，建议最好是使用 Java 规范的字段/属性命名风格，然后就可以去掉类似的注解了：

```java
@SuppressWarnings({"checkstyle:MemberName", "checkstyle:ParameterName"})
```

可以把 Jackson 相关的依赖（那些序列化/反序列化的注解）从 RPC 接口使用的类型中剥离出去，使用 Jackson 的 Mixin 机制好像可以做到。把使用 Jackson 序列化和反序列化的那些实现代码做成单独的包。

Jackson 是使用 Spring Boot 开发后端服务时默认使用的 JSON 库，有很多人在开发后端时并不希望再引入另外的 JSON 库（Fast JSON、GSON 等）依赖。


> 同样，对于 HTTP Client 库的使用不同的人其实也有不同的偏好。比如有的人可能会希望使用 Apache HTTP Client 库。所以建议这些都剥离到单独的包里。

### BCS

另外就是 BCS 的序列化/反序列化（加上交易的签名工具之类？），建议也是单独做成单独的包。因为如果我是做链下的查询服务、Indexer 服务之类，并不需要用到它们。

### 包划分

所以，是不是可以考虑这么划分包（底层的/被依赖的包排在前面），包名前缀下面先用 xxx 表示（MoveFuns 赞助一下？给我们开发者定期发点”薪水“，我们可以考虑用 MoveFuns 来命名这些包啊：）：


1. xxx-rpc-beans（或 xxx-rpc-common？名称待定）包。全部用于 RPC 调用都是 POJO，不引入对特定 JSON 库的依赖。
2. xxx-bcs 包。包含 BCS 序列化/反序列化相关的功能。
3. xxx-jackson 包。包含使用 Jackson 序列化/反序列化的功能。
4. xxx-gson 包。包含使用 GSON 序列化/反序列化的代码。
5. xxx-okhttp（或者叫其他名字？待定）包。使用上面的基础的包实现 Sui4J 目前已有的功能
6. xxx-jackson-rpc （我随便起的名字，待定）包。使用上面的基础包实现我那个 Sui-Java-SDK 目前已有的功能呢。供喜欢 Jackson + okHttp 组合的开发者使用。

后两个包是不是还是抽取出什么公用的基础包来？感觉后面可以慢慢探讨、重构。开始的时候可能这么划分已经够细了。

### 对静态类型的支持

有一点需要特别提示的就是，我希望在那个 xxx-rpc-beans（名称待定）包里面，保留对我现在大量使用的这样的方法的支持：

```java
public <T> SuiMoveObjectResponse<T> getMoveObject(String objectId, SuiObjectDataOptions options, Class<T> objectType) {
    options.setShowContent(true);// set showContent to true to get the parsed JSON content
    List<Object> params = new ArrayList<>();
    params.add(objectId);
    params.add(options);
    JSONRPC2Request jsonrpc2Request = new JSONRPC2Request("sui_getObject", params, System.currentTimeMillis());
    try {
        JSONRPC2Response<SuiMoveObjectResponse<T>> jsonrpc2Response = jsonrpc2Session
                .sendAndGetParametricTypeResult(jsonrpc2Request, SuiMoveObjectResponse.class, objectType);
        assertSuccess(jsonrpc2Response);
        return jsonrpc2Response.getResult();
    } catch (JSONRPC2SessionException e) {
        throw new RuntimeException(e);
    }
}
```

我感觉在做特定应用的链下查询服务的时候，直接给一个接口，支持获得特定静态对象的结果还是很有用的，没有必要先让 JSON 库反序列化为 Map 然后再让接口使用者自己转为想要的目标静态对象。

这个方法的用法：

```java
@Test
void testGetMoveObject_getDynamicFields_getDynamicFieldMoveObject_D() throws MalformedURLException, JsonProcessingException {
    SuiJsonRpcClient client = new SuiJsonRpcClient("https://fullnode.devnet.sui.io/");
    SuiMoveObjectResponse<Order> getObjectDataResponse = client.getMoveObject(
            "0x50dc4c763b4f3df257a4557345bced2097bd0e32ad4200493527bcfdd1192546",
            new SuiObjectDataOptions(),
            Order.class
    );
    System.out.println(getObjectDataResponse);
    Order order = getObjectDataResponse.getData().getContent().getFields();
    //...
    
```

---

同样，获取事件的时候也是如此：

```java
public <F> PaginatedMoveEvents<F> queryMoveEvents(String moveEvent,
                                                  EventId cursor, int limit, boolean descendingOrder,
                                                  Class<F> moveEventFieldsType) {
    List<Object> params = new ArrayList<>();
    params.add(new SuiEventFilter.MoveEventType(moveEvent));
    params.add(cursor);
    params.add(limit);
    params.add(descendingOrder);
    JSONRPC2Request jsonrpc2Request = new JSONRPC2Request("suix_queryEvents", params,
            System.currentTimeMillis());
    try {
        JSONRPC2Response<PaginatedMoveEvents<F>> jsonrpc2Response = getJSONRPC2Session()
                .sendAndGetParametricTypeResult(jsonrpc2Request, PaginatedMoveEvents.class, moveEventFieldsType);
        assertSuccess(jsonrpc2Response);
        return jsonrpc2Response.getResult();
    } catch (JSONRPC2SessionException e) {
        throw new RuntimeException(e);
    }
}
```

