Десериализация в объект Java с использованием JSON? - PullRequest
4 голосов
/ 11 августа 2010

Я должен получить следующий JSON:

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

}

Вот еще один пример:

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

}

Мне нужно проанализировать эти JSON, чтобы вызвать указанный метод с указанными аргументами в качестве параметров.

Самый простой способ (для меня) - использовать JsonParser, чтобы получить JsonElement, затем JsonObject, а затем извлечь каждое значение, используя .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();

}

И тогда я мог бы вызвать указанный метод с соответствующими аргументами (используя switch).

Мне было просто интересно, будет ли более легкий (или более красивый) способ добиться этого.

Я мог бы использовать .fromJson() для извлечения объекта, но я не знаю, как мне создать свой класс для этого (есть что-то вроде массива аргументов, и не все методы имеют одинаковое количество аргументов).

Я новичок в JSON (и в Java тоже).

Мне удалось сделать это:

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

Кажется, это работает ... но так как я новичок в Java, я не уверен, что это правильный способ сделать это. Что ты думаешь?

Ответы [ 4 ]

4 голосов
/ 12 августа 2010

Возможно, сериализатор Gson Map достаточно умен, чтобы десериализовать это?

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

(У меня нет времени на тщательное тестирование, но я надеюсь, что это сработает! :))

0 голосов
/ 11 февраля 2014

Вы должны десериализовать код дважды, потому что он входит в массив других

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 голосов
/ 12 августа 2010

Проблема, связанная с тем, как вы обычно делаете это с помощью Gson, заключается в том, что JSON "args" - это объект, который, основываясь на ваших примерах, может иметь переменное количество полей (аргументы и их имена).Было бы лучше, если бы "args" был просто массивом JSON-аргументов метода (без имен аргументов), поскольку вы все равно не сможете использовать имена аргументов при вызове метода.Тогда вы могли бы написать простой класс, такой как:

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

, который можно было бы проанализировать из JSON.

Я предполагаю, что вы не можете изменить формат, который вы получаете, хотя,поэтому другой вариант может заключаться в том, чтобы использовать тот же класс, который я перечислил выше, но зарегистрировать для него пользовательский 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);
}

Затем вы можете использовать отражение для вызова метода.В идеале, метод, который делает это, будет методом MethodCall, поэтому после получения объекта MethodCall вы просто напишите call.callMethod(obj), где obj будет объектом, для которого вы хотите вызвать метод.

Редактировать

Формат JSON, который будет наиболее простым для вызова методов Java, будет выглядеть примерно так:

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

Gson может автоматически преобразовывать массив JSON в List или массив, который затем можно использовать для вызова метода через отражение.

0 голосов
/ 11 августа 2010

Использовать отражение 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...