如何使用 jsonrpc4j 客户端将对象作为参数传递?

Posted

技术标签:

【中文标题】如何使用 jsonrpc4j 客户端将对象作为参数传递?【英文标题】:How do I pass objects as parameters using the jsonrpc4j client? 【发布时间】:2020-09-17 16:37:38 【问题描述】:

我正在尝试编写一个 Kotlin 客户端,它使用 jsonrpc4j (https://github.com/briandilley/jsonrpc4j) 与运行在 android 设备上的服务器通信。这是我正在使用的服务器:https://github.com/xiaocong/android-uiautomator-server

调用采用单个参数的方法,例如 null 或单个 String 对象可以正常工作。但是,如果我尝试调用 boolean exist(Selector obj); 方法,则方法匹配不起作用并且我得到一个异常:

Invalid method parameters
com.googlecode.jsonrpc4j.JsonRpcClientException: Invalid method parameters
    at com.googlecode.jsonrpc4j.DefaultExceptionResolver.createJsonRpcClientException(DefaultExceptionResolver.java:53)
    at com.googlecode.jsonrpc4j.DefaultExceptionResolver.resolveException(DefaultExceptionResolver.java:28)
    at com.googlecode.jsonrpc4j.JsonRpcClient.handleErrorResponse(JsonRpcClient.java:272)
    at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:196)
    at com.googlecode.jsonrpc4j.JsonRpcClient.readResponse(JsonRpcClient.java:531)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:148)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:118)
    at com.googlecode.jsonrpc4j.JsonRpcHttpClient.invoke(JsonRpcHttpClient.java:176)
    ...

https://github.com/xiaocong/android-uiautomator-server/blob/master/app/src/androidTest/java/com/github/uiautomator/stub/AutomatorService.java#L400

这是我的测试代码:

@Test fun methodTest() 
    val client = JsonRpcHttpClient(URL("http://localhost:9008/jsonrpc/0"))
    val invoke = client.invoke("ping", null, Object::class.java)
    println(invoke) // prints "pong"
    val selector = Selector()
    selector.packageName = "com.company.appname"
    val exists = client.invoke("exist", selector, Boolean::class.java) // throws Exception
    println(exists)

我调试了服务器代码,看起来好像 Selector 类型丢失了,所有参数都“扁平化”为字符串列表:

09-17 18:05:58.216 D/UIAutomatorStub(17611):URI:/jsonrpc/0,方法: POST,标头:content-length=620,remote-addr=127.0.0.1, http-client-ip=127.0.0.1, 主机=localhost:9008, 内容类型=应用程序/json-rpc,连接=保持活动, 缓存控制=无缓存,编译指示=无缓存,用户代理=Java/1.8.0_265, 接受=文本/html、图像/gif、图像/jpeg、*; q=.2, /; q=.2,参数, NanoHttpd.QUERY_STRING=null,文件: postData="id":"61840997","jsonrpc":"2.0","method":"exist","params":"packageName":"com.company.appname","text":null ,"className":null,"description":null,"textContains":null,"textMatches":null,"textStartsWith":null,"classNameMatches":null,"descriptionContains":null,"descriptionMatches":null," descriptionStartsWith":null,"checkable":false,"checked":false,"clickable":false,"scrollable":false,"longClickable":false,"enabled":false,"focusable":false,"focused" :false,"selected":false,"packageNameMatches":null,"resourceId":null,"resourceIdMatches":null,"mask":0,"childOrSiblingSelector":[],"childOrSibling":[],"index" :0,"instance":0

我将Selector 类从服务器复制到宿主项目中并按原样使用它: https://github.com/xiaocong/android-uiautomator-server/blob/master/app/src/androidTest/java/com/github/uiautomator/stub/Selector.java

我也尝试用 @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="class") 注释类,但唯一的效果是它为“params”添加了一个“类”属性。

如何使它工作,以便我可以在客户端使用服务器的参数类型?

【问题讨论】:

为什么不试试 Kotlin 序列化:github.com/Kotlin/kotlinx.serialization 【参考方案1】:

任何参数都必须传递到数组中。因此,在您的情况下,JAVA 中的代码将是:

Boolean exists = client.invoke("exist", new Object[]selector, Boolean.class);

【讨论】:

以上是关于如何使用 jsonrpc4j 客户端将对象作为参数传递?的主要内容,如果未能解决你的问题,请参考以下文章

如何将复杂的 Java 类对象作为参数传递给 Spark 中的 Scala UDF?

JSON序列化时为jsonrpc4j null

如何将json POST数据作为对象传递给Web API方法?

如何使用 Alamofire 将单个对象作为参数发送

如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)

如何使用react将多个参数作为url中的对象传递