使用 JSON 反序列化为 Java 对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3461473/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Deserialization to a Java object using JSON?
提问by S Macgowan
I must receive the following JSON:
我必须收到以下 JSON:
{
"method":"methodName1",
"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.
我需要解析这些 JSON,以便使用指定的“args”作为参数调用指定的方法。
The easy way (for me) would be to use a JsonParserto get a JsonElement, then a JsonObjectand then extract each value using .get()... something like this:
简单的方法(对我来说)是使用 aJsonParser来获取 a JsonElement,然后使用 aJsonObject然后使用.get()...提取每个值,如下所示:
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).
然后我可以使用适当的参数(使用 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).
我可以.fromJson()用来检索一个对象,但我不知道我应该如何创建我的类来这样做(有一些类似于 args 的数组,并非所有方法都具有相同数量的 args)。
I'm new to JSON (and to Java as well).
我是 JSON(以及 Java)的新手。
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?
它似乎有效......但由于我是 Java 新手,我不确定这是正确的方法。你怎么认为?
采纳答案by Steven Schlansker
Perhaps the Gson Map serializer is smart enough to deserialize that?
也许 Gson Map 序列化器足够聪明,可以反序列化它?
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! :) )
(没有时间彻底测试它,但我希望它有效!:))
回答by borchvm
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();
}
回答by ColinD
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:
以您通常使用 Gson 的方式执行此操作的问题在于,JSON"args"是一个对象,根据您的示例,该对象可以具有可变数量的字段(参数及其名称)。如果"args"只是方法的参数的 JSON 数组(没有参数名称)会更好,因为无论如何在调用方法时都无法使用参数名称。然后你可以写一个简单的类,如:
class MethodCall {
private String method;
private List<String> args;
...
}
which could be parsed from the JSON.
可以从 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 JsonDeserializerfor it. That might look something like this:
不过,我猜您无法更改收到的格式,因此另一种选择可能是使用我上面列出的相同类,但JsonDeserializer为其注册自定义。这可能看起来像这样:
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 MethodCallobject you'd just write call.callMethod(obj)with objbeing the object you want the method called on.
然后您可以使用反射来调用该方法。理想情况下,它会是一个方法的方法MethodCall,所以得到后MethodCall对象你只写call.callMethod(obj)有obj是你想呼吁方法的对象。
Edit
编辑
The JSON format that would be easiest for calling Java methods would be something like:
最容易调用 Java 方法的 JSON 格式类似于:
{
"method":"methodName2",
"args": [
"arg1Value",
"arg2Value",
"arg3Value",
"arg4Value"
]
}
Gson can automatically convert the JSON array into a Listor array which could then be used to invoke the method via reflection.
Gson 可以自动将 JSON 数组转换为Listor 数组,然后可以使用该数组通过反射调用该方法。
回答by bluedevil2k
Use Java reflection.
使用 Java 反射。
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);

