I must receive the following JSON:
{
"method":"methodName1",
"开发者_StackOverflow社区args":{
"arg1Name":"arg1Value",
"arg2Name":"arg2Value"
}
}
Here's another example:
{
"method":"methodName2",
"args":{
"arg1Name":"arg1Value",
"arg2Name":"arg2Value"
"arg3Name":"arg3Value"
"arg4Name":"arg4Value"
}
}
I need to parse those JSONs in order to call the specified method with the specified "args" as parameters.
The easy way (for me) would be to use a JsonParser
to get a JsonElement
, then a JsonObject
and then extract each value using .get()
... something like this:
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(jsonString);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
String method = jsonObject.get("method").getAsString();
JsonObject jsonArgs = jsonObject.getAsJsonObject("args");
String arg1 = jsonArgs.get("arg1Name").getAsString();
String arg2 = jsonArgs.get("arg2Name").getAsString();
}
And then I could call the specified method with the appropriate arguments (using a switch
).
I was just wondering if there would be an easier (or prettier) way to achieve this.
I could use .fromJson()
to retrieve an object instead, but I don't know how I should create my class to do so (there's something like an array of args and not all methods have the same number of args).
I'm new to JSON (and to Java as well).
I've managed to do this:
import lotus.domino.*;
import com.google.gson.*;
import java.io.*;
import java.lang.reflect.Method;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
String jsonReceived = "{\"method\":\"methodName\",\"args\":{\"arg1Name\":\"arg1Value\",\"arg2Name\":\"arg2Value\"}}";
Gson gson = new Gson();
MethodCall mc = gson.fromJson(jsonReceived, MethodCall.class);
JavaAgent ja = new JavaAgent();
Method method = getClass().getMethod(mc.getMethod(), MethodCall.class);
String s = (String)method.invoke(ja, mc);
PrintWriter pw = getAgentOutput();
pw.println(s);
} catch(Exception e) {
e.printStackTrace();
}
}
public String methodName(MethodCall mc) {
String s = mc.getArgs().get("arg1Name") + " " + mc.getArgs().get("arg2Name");
return s;
}
}
import java.util.*;
public class MethodCall {
private String method;
private Map<String, String> args;
public String getMethod() {
return method;
}
public Map<String, String> getArgs() {
return args;
}
}
It seems to work... but since I'm new to Java, I'm not sure that's the proper way to do it. What do you think?
Perhaps the Gson Map serializer is smart enough to deserialize that?
public class MethodCall {
private String method;
private Map<String, String> args;
}
(Don't have the moment to test it thoroughly, but I hope it works! :) )
The problem with doing this the way you normally would using Gson is that the JSON "args"
is an object that, based on your examples, can have a variable number of fields (the arguments and their names). It would be better if "args"
were just a JSON array of arguments to the method (with no argument names) since you won't be able to use the argument names when calling the method anyway. Then you could write a simple class like:
class MethodCall {
private String method;
private List<String> args;
...
}
which could be parsed from the JSON.
I'm guessing you can't change the format you're receiving, though, so another option might be to use the same class I listed above, but register a custom JsonDeserializer
for it. That might look something like this:
public MethodCall fromJson(JsonElement json, Type typeOfT,
JsonDeserializationContext context)
throws JsonParseException {
JsonObject obj = json.getAsJsonObject();
String method = obj.get("method").getAsString();
JsonObject argsObj = obj.getAsJsonObject("args");
List<String> args = new ArrayList<String>();
for(Map.Entry<String,JsonElement> entry : argsObj.entrySet()) {
args.add(entry.getValue().getAsString());
}
return new MethodCall(method, args);
}
You could then use reflection to call the method. Ideally the method that does that would be a method on MethodCall
, so after getting the MethodCall
object you'd just write call.callMethod(obj)
with obj
being the object you want the method called on.
Edit
The JSON format that would be easiest for calling Java methods would be something like:
{
"method":"methodName2",
"args": [
"arg1Value",
"arg2Value",
"arg3Value",
"arg4Value"
]
}
Gson can automatically convert the JSON array into a List
or array which could then be used to invoke the method via reflection.
You must deserialize the code twice because it comes in an array of other
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(jsonString);
if (jsonElement.isJsonObject()) {
JSONObject jsonObject = jsonElement.getAsJsonObject();
String method = jsonObject.get("method").getAsString();
JSONObject jsonArgs = (JSONObject) jsonObject.get("args");
String arg1 = jsonArgs.get("arg1Name").getAsString();
String arg2 = jsonArgs.get("arg2Name").getAsString();
}
Use Java reflection.
List<String> args = new ArrayList<String>();
// add the args to the list here
Method method = myClass.getClass().getMethod(method, List.class);
Object o = method.invoke(myClass, args);
精彩评论