使用GSon从JSon转换为多个未知的Java对象类型

Abe*_*Abe 13 java json gson netty

我有一个netty解码器,它使用GSon将来自Web客户端的JSon转换为适当的java对象.要求是:客户端可以发送不相关的类,A类,B类,C类等,但我想在管道中使用相同的单例解码器实例进行转换(因为我使用spring进行配置).我面临的问题是我需要class事先知道对象.

public Object decode()
{
    gson.fromJson(jsonString, A.class);
}
Run Code Online (Sandbox Code Playgroud)

这不能解码B或C.我的库的用户现在需要为每个类编写单独的解码器,而不是稍后编译.我可以看到这样做的唯一方法是从Web客户端传递JSon字符串中的类名称"org.example.C",在解码器中解析它然后Class.forName用来获取类.有一个更好的方法吗?

Pom*_*Pom 9

GSon必须知道匹配json字符串的类.如果你不想用fromJson()提供它,你可以在Json中实际指定它.一种方法是定义接口并在其上绑定适配器.

喜欢 :

  class A implements MyInterface {
    // ...
  }

  public Object decode()
  {
    Gson  gson = builder.registerTypeAdapter(MyInterface.class, new MyInterfaceAdapter());
    MyInterface a =  gson.fromJson(jsonString, MyInterface.class);
  }
Run Code Online (Sandbox Code Playgroud)

适配器可以像:

public final class MYInterfaceAdapter implements JsonDeserializer<MyInterface>, JsonSerializer<MyInterface> {
  private static final String PROP_NAME = "myClass";

  @Override
  public MyInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    try {
      String classPath = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
      Class<MyInterface> cls = (Class<MyInterface>) Class.forName(classPath);

      return (MyInterface) context.deserialize(json, cls);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }

    return null;
  }

  @Override
  public JsonElement serialize(MyInterface src, Type typeOfSrc, JsonSerializationContext context) {
    // note : won't work, you must delegate this
    JsonObject jo = context.serialize(src).getAsJsonObject();

    String classPath = src.getClass().getName();
    jo.add(PROP_NAME, new JsonPrimitive(classPath));

    return jo;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是绝对错误的.Gson可以将任何有效的JSON反序列化为语法树,如下所示:`gson.fromJson(json,JsonElement.class)`.您可以根据需要解释由JSON数组(列表),JSON对象(映射)和JSON基元(数字,字符串,布尔值,null)组成的语法树. (2认同)

Mik*_*ikO 5

假设您有以下两种可能的JSON响应:

{
  "classA": {"foo": "fooValue"}
}
  or
{
  "classB": {"bar": "barValue"}
}
Run Code Online (Sandbox Code Playgroud)

您可以创建这样的类结构:

public class Response {
  private A classA;
  private B classB;
  //more possible responses...
  //getters and setters...
}

public class A {
  private String foo;
  //getters and setters...
}

public class B {
  private String bar;
  //getters and setters...
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以解析任何可能的JSON响应:

Response response = gson.fromJson(jsonString, Response.class);
Run Code Online (Sandbox Code Playgroud)

Gson将忽略与类结构中的任何属性不对应的所有JSON字段,因此您可以调整单个类来解析不同的响应...

然后你可以检查哪个属性classA,classB...不是null,你会知道你收到了哪个响应.