Java 反序列化泛型类Jackson或Gson

Java 反序列化泛型类Jackson或Gson,java,json,jackson,gson,Java,Json,Jackson,Gson,从.NET的角度来看,我有一个泛型类,定义如下 public class SyncWrapper<T, I> { public IList<T> Data { get; set; } public IList<I> DeleteIds { get; set; } public DateTime LastSyncDateTime { get; set; } } ..或者这(通常情况下,deleteID将为null) 对于上面的json,

从.NET的角度来看,我有一个泛型类,定义如下

public class SyncWrapper<T, I>
{
    public IList<T> Data { get; set; }
    public IList<I> DeleteIds { get; set; }
    public DateTime LastSyncDateTime { get; set; }
}
..或者这(通常情况下,deleteID将为null)

对于上面的json,我将映射到一个SyncWrapper,其中T是Company

public class Company extends ModelBase {

    private String name;

    public Company(UUID id, String name) {
        super(id);
        setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我建议用杰克逊来做这个;它有一个更清晰的API,并且不需要创建一个新类型作为Gson(您必须扩展一个类才能做到这一点)

例如:

public static <T> T fromJsonToGenericPojo(
        String json, Class<?> classType, Class<?>... genericTypes) {

    JavaType javaType = TypeFactory.defaultInstance()
            .constructParametricType(classType, genericTypes);

    try {
        return OBJECT_MAPPER.readValue(json, javaType);
    } catch (IOException e) {
        LOGGER.error(e.getMessage(), e);
        throw new IllegalArgumentException(e);
    }
}
jsontogenericpojo中的公共静态T(
字符串json、类classType、类…genericTypes){
JavaType JavaType=TypeFactory.defaultInstance()
.ConstructParameterType(类类型、泛型);
试一试{
返回OBJECT_MAPPER.readValue(json,javaType);
}捕获(IOE异常){
LOGGER.error(e.getMessage(),e);
抛出新的IllegalArgumentException(e);
}
}
以下是问题:

Java类中的字段名与JSON中的字段名不匹配;资本化很重要。这就是为什么你在解析后什么都没有得到

我将使用Gson的例子,因为我对这一点了如指掌。你可以在杰克逊做同样的事情,但我需要查一下:

public class SyncWrapper<T, I> {

    @SearializedName("LastSyncDateTime")
    private DateTime lastSyncDateTime;
    @SearializedName("Data")
    private Collection<T> data;
    @SearializedName("DeleteIds")
    private Collection<I> deleteIds;
现在,您的字段将匹配。下一个问题是
UUID
类。Java中的类不是字符串;它是一个生成UUID的类。只需对Java类中保存该字符串的类型使用
String

DateTime
类。。。同样的问题。最重要的是,在日期的JSON中有一个奇怪的值。您要么希望将其存储为
字符串
,要么必须编写一个自定义反序列化程序来处理它

有了这些变化,我觉得你可以走了

编辑以从注释中添加:如果您确实需要Java
UUID
类,而不仅仅是
字符串
表示,您可以编写一段代码来为您解决这一问题:

class UUIDDeserializer implements JsonDeserializer<UUID>
{
    @Override
    public UUID deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
    {
        return UUID.fromString(je.getAsString());
    }
}

这将使用
UUID
实例填充类中的
UUID
类型字段。这与处理这个时髦的日期值需要做的事情是一样的。

如果没有看到JSON示例,这是不可能回答的。你展示的Gson和Jackson片段非常好。。。但是JSON似乎不匹配(我猜有一个问题是试图使用
UUID
类)@BrianRoach-谢谢你的评论,我已经更新了这个问题,展示了一些JSON和一个示例类。关于UUID,你认为可能是什么问题?像UUID这样的类型可以用@McDowell-Sure来处理,如果这样做有意义的话。使用
UUID
。。。我不知道有。这实际上取决于最终用例。大多数情况下,您只需要使用UUID的字符串表示形式。尽管我最终使用了Jackson库,但问题的主要原因是外壳。正如您所说的@BrianRoach“资本化很重要”。非常感谢您的帮助。对于新手提出的问题,很抱歉:您是否可以使用以下语法SyncWrapper results=MyUtils.fromJsonToGeneric(json,SyncWrapper.class,Company.class,UUID.class)?对尽管我认为编译器应该能够推断类型(至少从Java 7中),并且不调用
MyUtils.fromJsonToGeneric()
,而是直接调用
MyUtils.fromJsonToGeneric()
。再说一次,我想,我没有核实。嗯,它不快乐。我认为这是因为UUID,但没有得到一个例外回来-这是令人担忧的。
{
  "Data": [
    {
      "Name": "Company A",
      "Id": "7d5d236c-c2b5-42dc-aea5-99e6752c8a52"
    },
    {
      "Name": "Company B",
      "Id": "44444444-0000-0000-0000-444444444444"
    },
    {
      "Name": "Company C",
      "Id": "249a4558-05c6-483f-9835-0056804791c9"
    }
  ],
  "DeleteIds": [
    "5f7873a6-b2ee-4566-9714-1577b81384f4",
    "1f224a39-16c3-441d-99de-8e58fa8f31c2"
  ],
  "LastSyncDateTime": "\/Date(1393580073773+0000)\/"
}
{
  "Data": [
    {
      "Name": "Company A",
      "Id": "7d5d236c-c2b5-42dc-aea5-99e6752c8a52"
    },
    {
      "Name": "Company B",
      "Id": "44444444-0000-0000-0000-444444444444"
    },
    {
      "Name": "Company C",
      "Id": "249a4558-05c6-483f-9835-0056804791c9"
    }
  ],
  "DeleteIds": null,
  "LastSyncDateTime": "\/Date(1393580073773+0000)\/"
}
public class Company extends ModelBase {

    private String name;

    public Company(UUID id, String name) {
        super(id);
        setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public static <T> T fromJsonToGenericPojo(
        String json, Class<?> classType, Class<?>... genericTypes) {

    JavaType javaType = TypeFactory.defaultInstance()
            .constructParametricType(classType, genericTypes);

    try {
        return OBJECT_MAPPER.readValue(json, javaType);
    } catch (IOException e) {
        LOGGER.error(e.getMessage(), e);
        throw new IllegalArgumentException(e);
    }
}
public class SyncWrapper<T, I> {

    @SearializedName("LastSyncDateTime")
    private DateTime lastSyncDateTime;
    @SearializedName("Data")
    private Collection<T> data;
    @SearializedName("DeleteIds")
    private Collection<I> deleteIds;
Gson g = new GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
             .build();
class UUIDDeserializer implements JsonDeserializer<UUID>
{
    @Override
    public UUID deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
    {
        return UUID.fromString(je.getAsString());
    }
}
Gson g = new GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
             .registerTypeAdapter(UUID.class, new UUIDDeserializer())
             .build();