开发者

Deserialization to a Java object using JSON?

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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜