反序列化通用类Jackson或Gson

时间:2014-02-27 17:17:58

标签: 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; }
}

我能够通过简单地调用...

从json创建这个对象的实例
JsonConvert.DeserializeObject<SyncWrapper<T, Guid>>(json);

现在我已经完成了将此代码移植到Java / Android的任务。以前从未接触过Java,我需要学习很多东西!

无论如何,到目前为止,我已经尝试过Gson和Jackson从json那里获得物品,但没有任何喜悦。我认为我无法使用<T>涉及gson.fromJson(json, SyncWrapper<T, UUID>.class)进行调用,例如因为Erasure类型存在问题!

到目前为止,我的努力看起来像这样....

GSON

Gson gson = new Gson();

SyncWrapper<MyClass, UUID> result = gson.fromJson(json, new TypeToken<SyncWrapper<MyClass, UUID>>() { }.getType());

这会编译,但结果是一个空的SyncWrapper

杰克逊

ObjectMapper mapper = new ObjectMapper();

SyncWrapper<MyClass, UUID> result = mapper.readValue(json, new TypeReference<SyncWrapper<MyClass, UUID>>() { });

这会编译但在执行时崩溃应用程序!!!

我的Java版SyncWrapper ....

public class SyncWrapper<T, I> {

    private DateTime lastSyncDateTime;
    private Collection<T> data;
    private Collection<I> deleteIds;

    public Collection<T> getData() {
        return data;
    }

    public void setData(Collection<T> data) {
        this.data = data;
    }

    public Collection<I> getDeleteIds() {
        return deleteIds;
    }

    public void setDeleteIds(Collection<I> deleteIds) {
        this.deleteIds = deleteIds;
    }

    public DateTime getLastSyncDateTime() {
        return lastSyncDateTime;
    }

    public void setLastSyncDateTime(DateTime lastSyncDateTime) {
        this.lastSyncDateTime = lastSyncDateTime;
    }
}

我被强大的力量所吸引(所有编程都是一样的不是吗?),所以任何帮助都非常感激。

我对使用哪个库(Gson,Jackson等)并不珍贵

更新

要反序列化的Json的一个例子......

{
  "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)\/"
}

..或者这个(通常,DeleteIds将为null)...

{
  "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)\/"
}

对于上面的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;
    }
}

2 个答案:

答案 0 :(得分:1)

以下是问题:

您的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;

这告诉Gson Java中的哪些字段映射到JSON中的字段。您也可以改为使用字段命名策略,因为看起来您的所有字段都是上层骆驼案例:

Gson g = new GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
             .build();

现在您的字段将匹配。下一个问题将是UUID类。 Java中的那个类不是字符串;它是一个生成UUID的类。只需使用String作为在Java类中保存它的类型。

DateTime类......同样的问题。最重要的是,你的日期JSON中有一些奇怪的值。您要么也想将其存储为String,要么您将不得不编写自定义反序列化来处理它。

随着这些变化,我觉得你很高兴。

编辑以从评论中添加:如果您确实需要Java UUID类而不仅仅是String表示,那么您可以编写一小块需要注意的代码这对你来说:

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

然后你可以用Gson注册:

Gson g = new GsonBuilder()
             .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
             .registerTypeAdapter(UUID.class, new UUIDDeserializer())
             .build();

这将使用UUID个实例填充您班级中的UUID个字段。这与你那个时髦的日期值有关。

答案 1 :(得分:0)

我建议使用Jackson;它有一个更清晰的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);
    }
}
相关问题