Spring JSON序列化,Gson反序列化

4

目前我在反序列化某些内部对象时遇到问题,在spring中,我使用@ResponseBody在输出之前初始化所有对象。

例如,这是一个响应:

[{id:1, location:{id:1, ... extra location data}},
 {id:2, location:1}
]

现在,GSON会抛出错误,因为它无法理解 location:1 已经在前一个对象中反序列化的位置对象。 反序列化是在以下方法中完成的:
@Override
public void handleReader(Reader reader) {
    try {
        String json = readerToString(reader);
        T object = getGson().fromJson(json, returnType);
        handleObject(object);
    } catch (Exception e) {
        Sentry.captureException(e);
    }
}

作为一个例子,如果我要通过一个普通的泛型类来调用它,我会使用类型Event[]作为T泛型类型以返回一个数组。
我该如何使用Gson修复这个问题或让Spring每次输出完整数据?理想情况下,我希望使用Gson修复,因为它可以大大减少带宽,但现在我并不是太在意。
我的Spring返回方法如下:
@Override
public List<T> list() {
    return service.findAll();
}

使用以下初始化:

@Override
@Transactional
public List<Event> findAll() {
    List<Event> list = eventRepository.findByArchivedFalse();
    for (Event event : list) {
        this.initialize(event);
    }
    return list;
}
@Override
public Event initialize(Event obj) {
    Hibernate.initialize(obj.getLocation());
    Hibernate.initialize(obj.getLocation().get... inner data here);
    return obj;
}

我想这将需要进行真正的结构审查,但如果可以的话,我希望保持结构大致相同。

1个回答

2

如果您不想改变JSON格式,那么您需要编写自定义反序列化器。但是,我建议您修改JSON格式。

选项1:修改JSON格式

我认为正确的做法是拥有两个单独的消息,例如:

{
  "uniqueLocations":
    [
      {"id":1, ... extra location details} ,
    ],
  "locationMap":
    [ 
      {"id":1,"location":1},
      {"id":2,"location":1}
      ... etc.
    ]
}

这样做更加明显,它将您的JSON分开,使得您总是在相同的位置拥有相同类型的数据。


选项2:使Gson能够执行更复杂的反序列化操作

如果您不想那样做,您可以编写自定义反序列化程序。最直接的方法是扩展TypeAdapter,只使用特定的具体类,而非参数化类型。但是,如果您要使用参数化类型,则必须使用TypeAdapterFactory

您可以在此处阅读有关如何执行此操作的更多信息:如何在Gson中实现TypeAdapterFactory?


很遗憾,我想改变JSON格式,但这意味着要更改超过3个不同平台的模型,目前并不是一个可行的选择。如果Gson不能自动完成,我会考虑让Spring提供完整数据(尽管听起来很糟糕)。谢谢! - Thomas Nairn
@ThomasNairn 这就是我回答的第二部分所讲述的内容,即如何让Gson自动完成它。 - durron597
嗯,这本身可能需要跨越两个平台半天的工作时间,现在并不是很可行。我认为如果我要花那么长时间,我可能还不如改变JSON的结构,但目前的时间限制下这也不太可能。再次感谢您的建议。 - Thomas Nairn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接