Skip to content

Commit

Permalink
Wrap primitive and array parameter into an array as in JSON-RPC 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dhuebner committed Mar 24, 2023
1 parent d9ccef3 commit 0aee913
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

Expand Down Expand Up @@ -42,6 +43,7 @@
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.Primitives;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
Expand Down Expand Up @@ -420,7 +422,7 @@ public void write(JsonWriter out, Message message) throws IOException {
if (params == null)
writeNullValue(out);
else
gson.toJson(params, params.getClass(), out);
handleParameter(out, params, requestMessage.getMethod());
} else if (message instanceof ResponseMessage) {
ResponseMessage responseMessage = (ResponseMessage) message;
out.name("id");
Expand All @@ -445,12 +447,24 @@ public void write(JsonWriter out, Message message) throws IOException {
if (params == null)
writeNullValue(out);
else
gson.toJson(params, params.getClass(), out);
handleParameter(out, params, notificationMessage.getMethod());
}

out.endObject();
}

protected void handleParameter(JsonWriter out, Object params, String method) {
boolean isSingleArray = (getParameterTypes(method).length == 1 && Collection.class.isInstance(params)
|| params.getClass().isArray());
boolean needsWrap = isSingleArray || params instanceof String || Primitives.isPrimitive(getClass())
|| Primitives.isWrapperType(params.getClass());
if (needsWrap) {
gson.toJson(List.of(params), List.class, out);
} else {
gson.toJson(params, params.getClass(), out);
}
}

protected void writeId(JsonWriter out, Either<String, Number> id) throws IOException {
if (id == null)
writeNullValue(out);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,59 +786,140 @@ public void testNotification_AllOrders() {


@Test
public void testParamUnwrap_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, Boolean.class);
public void testWrapPrimitive_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, String.class);

var request = new RequestMessage();
request.setId(1);
request.setMethod(handler.getMethodProvider().resolveMethod(null));
request.setParams(new boolean[] { true }); // fake wrapped primitive [true] for JsonRpc 2.0

RequestMessage message = (RequestMessage) handler.parseMessage(request.toString());

request.setParams("param");

// check primitive was wrapped into array
assertEquals("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"testMethod\",\"params\":[\"param\"]}", handler.serialize(request));
}

@Test
public void testUnwrapPrimitive_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, String.class);
var request = "{\n"
+ " \"jsonrpc\": \"2.0\",\n"
+ " \"id\": 1,\n"
+ " \"method\": \"testMethod\",\n"
+ " \"params\": [\n"
+ " \"param\"\n"
+ " ]\n"
+ "}";
// Check parse - unwrap primitive
assertEquals(true, message.getParams());

RequestMessage message = (RequestMessage) handler.parseMessage(request);
assertEquals("param", message.getParams());
}

@Test
public void testArrayParamUnwrap_JsonRpc2_0() {
public void testWrapArray_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, new TypeToken<List<Boolean>>() {
}.getType());

var request = new RequestMessage();
request.setId(1);
request.setMethod(handler.getMethodProvider().resolveMethod(null));
request.setParams(List.of(true,false));

// check primitive was wrapped into array
assertEquals("{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"testMethod\",\"params\":[[true,false]]}", handler.serialize(request));

}

@Test
public void testUnwrapArray_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, new TypeToken<List<Boolean>>() {
}.getType());

var request = "{\n"
+ " \"jsonrpc\": \"2.0\",\n"
+ " \"id\": 1,\n"
+ " \"method\": \"testMethod\",\n"
+ " \"params\": [\n"
+ " [\n"
+ " true\n"
+ " true, false\n"
+ " ]\n"
+ " ]\n"
+ "}";
RequestMessage message = (RequestMessage) handler.parseMessage(request);

// Check parse - unwrap array
assertEquals(List.of(true), message.getParams());
assertEquals(List.of(true, false), message.getParams());

}

@Test
public void testWrapMultipleParams_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, Boolean.class, String.class);

var request = new RequestMessage();
request.setMethod(handler.getMethodProvider().resolveMethod(null));
request.setParams(List.of(true, "param2"));
// Check serialize - wrap primitive wrapper
assertEquals("{\"jsonrpc\":\"2.0\",\"id\":null,\"method\":\"testMethod\",\"params\":[true,\"param2\"]}",
handler.serialize(request));

}

@Test
public void testMultiParamUnwrap_JsonRpc2_0() {
public void testUnwrapMultipleParams_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, Boolean.class, String.class);

var request = "{\n"
+ " \"jsonrpc\": \"2.0\",\n"
+ " \"id\": 1,\n"
+ " \"method\": \"testMethod\",\n"
+ " \"params\": [\n"
+ " true,\n"
+ " \"param2\"\n"
+ " ]\n"
+ "}";
RequestMessage message = (RequestMessage) handler.parseMessage(request);

// Check parse - unwrap array
assertEquals(List.of(true, "param2"), message.getParams());

}
@Test
public void testWrapMultipleParamsWithArray_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, new TypeToken<List<Boolean>>() {
}.getType(), String.class);

var request = new RequestMessage();
request.setId(1);
request.setMethod(handler.getMethodProvider().resolveMethod(null));
request.setParams(List.of(true, "string")); // fake wrapped array [true, string] for JsonRpc 2.0
request.setParams(List.of(List.of(true, false), "param2"));
// Check serialize - wrap primitive wrapper
assertEquals("{\"jsonrpc\":\"2.0\",\"id\":null,\"method\":\"testMethod\",\"params\":[[true,false],\"param2\"]}",
handler.serialize(request));

}

@Test
public void testUnwrapMultipleParamsWithArray_JsonRpc2_0() {
MessageJsonHandler handler = createSimpleRequestHandler(String.class, new TypeToken<List<Boolean>>() {
}.getType(), String.class);

RequestMessage message = (RequestMessage) handler.parseMessage(request.toString());
var request = "{\n"
+ " \"jsonrpc\": \"2.0\",\n"
+ " \"id\": 1,\n"
+ " \"method\": \"testMethod\",\n"
+ " \"params\": [\n"
+ " [\n"
+ " true,\n"
+ " false\n"
+ " ],\n"
+ " \"param2\"\n"
+ " ]\n"
+ "}";
RequestMessage message = (RequestMessage) handler.parseMessage(request);

// Check parse - unwrap array
assertEquals(request.getParams(), message.getParams());
assertEquals(List.of(List.of(true, false),"param2"), message.getParams());

}

private static MessageJsonHandler createSimpleRequestHandler(Class<?> returnType, Type... paramType) {
JsonRpcMethod requestMethod = JsonRpcMethod.request("testMethod", returnType, paramType);
MessageJsonHandler handler = new MessageJsonHandler(Map.of(requestMethod.getMethodName(), requestMethod));
Expand Down

0 comments on commit 0aee913

Please sign in to comment.