Removing deserialization to a Java object using JSON?

I should get the following JSON:

{ "method":"methodName1", "args":{ "arg1Name":"arg1Value", "arg2Name":"arg2Value" } } 

Here is another example:

 { "method":"methodName2", "args":{ "arg1Name":"arg1Value", "arg2Name":"arg2Value" "arg3Name":"arg3Value" "arg4Name":"arg4Value" } } 

I need to parse these JSONs to call the specified method with the specified "args" as parameters.

An easy way (for me) would be to use JsonParser to get a JsonElement , then a JsonObject , and then retrieve each value with .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 switch ).

I'm just wondering if there will be an easier (or more beautiful) way to achieve this.

I could use .fromJson() to retrieve the object instead, but I don't know how I should create my class for this (there is something like an array of arguments, and not all methods have the same number of arguments).

I am new to JSON (and Java).

I 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; } } 

This seems to work ... but since I'm new to Java, I'm not sure if this is the right way to do this. What do you think?

+4
source share
4 answers

Is the Gson Map serializer smart enough to deserialize this?

 public class MethodCall { private String method; private Map<String, String> args; } 

(I don’t have time to check it out completely, but I hope it works! :))

+4
source

The problem with the way you usually use Gson is that JSON "args" is an object that, based on your examples, can have a variable number of fields (arguments and their names). It would be better if "args" was just an array of JSON arguments for the method (without argument names), since you cannot use the argument names when calling the method in any case. Then you can write a simple class, for example:

 class MethodCall { private String method; private List<String> args; ... } 

which could be parsed from JSON.

I assume that you cannot change the format you are getting, so another option might be to use the same class as I listed above, but register a JsonDeserializer for it. It 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); } 

Then you can use reflection to call the method. Ideally, the method that does this will be a method on MethodCall , so after receiving the MethodCall object MethodCall you simply write call.callMethod(obj) with obj being the object you want to call the method on.

Edit

The JSON format, which will be the easiest to call Java method calls, will be something like this:

 { "method":"methodName2", "args": [ "arg1Value", "arg2Value", "arg3Value", "arg4Value" ] } 

Gson can automatically convert a JSON array to a List or an array, which can then be used to invoke a method through reflection.

0
source

You have to deserialize the code twice because it goes into an array of others

 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(); } 
0
source

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); 
-2
source

All Articles