简体   繁体   中英

Returned JSON object does not respect inheritance?

I have a Google Cloud Endpoint API which returns a Product object. This product object itself contains another object Brand which is very large (id, name, text, description, image URLs, ...). When getting a list of products I don't need the whole information inside Brand , just the id and title.

So I tried to factor out Brand to a base class BrandBase which only contains a limited set of properties (only id and title). And inside Product in the public BrandBase getBrand() method I return a BrandBase object.

But then looking at the JSON output from Google Cloud Endpoints - I still get the whole Brand content (including all text, description, etc). So it looks like Google Cloud Endpoint just looks at the object-type and serializes everything regardless of the specified return type in the class itself?

@Entity
public class Product {
  @Id
  private Long id;

  @Index
  private Ref<BrandBase> brand;

  public BrandBase getBrand() {
    return brand.get();
  }

  public void setBrand(BrandBase brand) {
    this.brand = Ref.create(brand);
  }
  ...
}

@Entity
public class Brand extends BrandBase {

  @Id
  private Long id;
  @Index
  private String name;
  private String text;
  private String contact;
  ... all getter/setter ...
}

public abstract class BrandBase {
  public abstract Long getId();
  public abstract String getName();
  public abstract void setName(String name);
}

the returned JSON is:

{
   "id": "6298002603900928",
   "title": "magna aliquyam erat, sed",
   "description": "Lorem ipsum dolor sit amet...",
   "brand": {
     "id": "6192449487634432",
     "name": "no",
     "text": "Lorem ipsum dolor sit amet, ...",
     "contact": "Lorem ipsum dolor..."
   }
 }

so it still contains text and contact - both are not specified in the BrandBase class.

Is this a bug or feature of Google Cloud Endpoints? Or are there other methods to get my desired behavior: I only want to have a shallow brand object inside the product - not the full brand object.

This is most certainly not a bug in endpoints, otherwise there would be no way to return polymorphic objects. Furthermore, every JSON serializer in existence works this same way.

I am not an expert in Cloud Endpoints, but I run across this architectural problem frequently and solve it in the same way:

You need to separate your data model from your API model. Passing entity objects back and forth only works for very simple entity objects and very simple applications. When you need different views of the objects for different callers, or to hide some pieces of data, it's time to think about separate DTOs.

For clients that are hard to upgrade (like native apps deployed in the field), you should start with DTOs immediately. This gives you the freedom to refactor your data model as you see fit while carefully controlling API compatibility. Yes, it's more work, but it will save you major headaches down the road. Use http://projectlombok.org/ to get rid of most of the boilerplate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM