Objectify List <Ref <T >>未由Google App Engine端点序列化

cvi*_*igo 6 java google-app-engine json endpoints objectify

您有两个相关的实体:客户和汽车.每个客户可以拥有多辆汽车

这是实体的摘要视图:

public class Customer 
{
    //Inner classes for partial loads
    public static class NoCars{}

    @Id protected String id;
    private String fullName;
    @Load(unless=NoCars.class) private List<Ref<Car>> cars;
}

public class Car
{
    @Id private Long id;
    private String makeAndModel;
    private String plateNumber;
}
Run Code Online (Sandbox Code Playgroud)

这是一种从数据存储区他拥有的所有汽车中检索客户的方法:

public Customer getCustomer(@Named("id") String customerId)
{
    Customer customer =  ofy().load().type(Customer.class).id(customerId).now();
    if (customer==null)
        throw new NotFoundException("customer not found");
    else
        return customer;
}
Run Code Online (Sandbox Code Playgroud)

endpoints.sh无法实现这一点,因为不支持List <Ref<Car>>返回类型Customer中包含的类型,但我发现这个有趣的解决方法:

我创建了CustomerPOJO

public class CustomerPOJO
{
    private String fullName;
}
Run Code Online (Sandbox Code Playgroud)

并修改了类Customer以从中扩展

public class Customer extends CustomerPOJO
{
    //Inner classes for partial loads
    public static class NoCars{}

    @Id protected String id;
    @Load(unless=NoCars.class) private List<Ref<Car>> cars = new ArrayList<>();
}
Run Code Online (Sandbox Code Playgroud)

和getter方法是:

public CustomerPOJO getCustomer(@Named("id") String customerId)
{
    Customer customer =  ofy().load().type(Customer.class).id(customerId).now();
    if (customer==null)
        throw new NotFoundException("customer not found");
    else
        return customer;
}
Run Code Online (Sandbox Code Playgroud)

请注意,该方法声明CustomerPOJO为返回类型,但它实际上返回"完整" Customer!

这适用于AppEngine 1.8.0 + Objectify 4.0 RC2.它通过一次通话获取客户数据和他拥有的所有汽车及其属性(makeAndModelplateNumber).

升级到1.8.9之后出现了这个问题.endpoints.sh仍然有效,因为返回类型是完全兼容的,但是在将Customer objecto解析为JSON时,我在运行时遇到异常.

java.io.IOException:com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException:直接自引用导致循环(通过引用链:entity.Customer ["cars"] - > java.util. ArrayList的[0] - > com.googlecode.objectify.impl.ref.LiveRef [ "钥匙"] - > com.googlecode.objectify.Key [ "根"])

在1.8.9中有效的任何其他解决方法吗?@ApiTransformer是唯一的选择吗?

cvi*_*igo 3

解决方案非常简单...只需隐藏 Ref 字段即可。它现在确实为 API 使用者提供了任何价值,但它只是给解析器带来了麻烦:

List<Ref<Car>>用以下方式替换了 getter 和 setter:

public List<Car> getCars()
{
    List<Car> ret = new ArrayList<>();
    Iterator<Ref<Car>> it = cars.iterator();

    while (it.hasNext())
        ret.add(it.next().getValue());
    return ret;
}

public void setCars(List<Car> newCars)
{
    Iterator<Car> it = newCars.iterator();

    while (it.hasNext())
        addCar(it.next());
}
Run Code Online (Sandbox Code Playgroud)

就这样