如何在Act中控制JSON返回对象的字段

本文讲述如何在Act应用中控制返回JSON对象的字段。不同的场景返回同样对象的时候可能会要求返回不同的对象字段。
最简单的例子是基本上所有返回User对象都要求去掉password字段。在这篇文章中我们讨论如何在Act应用中实现对JSON返回的控制。

首先创建一个Article类,以及对该资源的RESTful服务接口:

  1. @Entity("article")
  2. public class Article extends MorphiaAdaptiveRecord<Article> {
  3. @Controller("article")
  4. public static class Service extends MorphiaDao<Article> {
  5. @GetAction
  6. public Iterable<Article> list() {
  7. return findAll();
  8. }
  9. @GetAction("{id}")
  10. public Article show(String id) {
  11. return findById(id);
  12. }
  13. @PostAction
  14. public Article create(Article article) {
  15. return save(article);
  16. }
  17. ...
  18. }
  19. }

这里我们看到可以通过 POST /article向服务提交article数据。假设我提交的数据是:

  1. {
  2. "title": "How to control JSON view in Actframework",
  3. "content": "BlahBlah",
  4. "author": "Gelin Luo",
  5. "language": "Java",
  6. "framework": "Actframework",
  7. "tags" : [
  8. {"name": "java"},
  9. {"name": "mvc"},
  10. {"name": "json"}
  11. ]
  12. }

我可以得到类似下面的返回:

  1. {
  2. "id": "58a6409ab6c6fe2138b67f10",
  3. "_created": "17/02/2017 11:15:22 AM",
  4. "content": "BlahBlah",
  5. "v": 1,
  6. "language": "Java",
  7. "author": "Gelin Luo",
  8. "title": "How to control JSON view in Actframework",
  9. "_modified": "17/02/2017 11:15:22 AM",
  10. "framework": "Actframework",
  11. "tags": [
  12. {
  13. "name": "java"
  14. },
  15. {
  16. "name": "mvc"
  17. },
  18. {
  19. "name": "json"
  20. }
  21. ]
  22. }

当我发出GET /article请求时,Article.Service.list()方法会响应并返回所有的article列表:

  1. [
  2. {
  3. "id": "58a6409ab6c6fe2138b67f10",
  4. "_created": "17/02/2017 11:15:22 AM",
  5. "content": "BlahBlah",
  6. "v": 1,
  7. "language": "Java",
  8. "author": "Gelin Luo",
  9. "title": "How to control JSON view in Actframework",
  10. "_modified": "17/02/2017 11:15:22 AM",
  11. "framework": "Actframework",
  12. "tags": [
  13. {
  14. "name": "java"
  15. },
  16. {
  17. "name": "mvc"
  18. },
  19. {
  20. "name": "json"
  21. }
  22. ]
  23. }
  24. ]

那如果我想控制返回列表的数据,让每项只返回authortitle,我可以在list()方法上面添加注解PropertySpec

  1. @GetAction
  2. @act.util.PropertySpec("author,title")
  3. public Iterable<Article> list() {
  4. return findAll();
  5. }

然后再发出GET /article请求,就可以得到下面的响应了:

  1. [
  2. {
  3. "author": "Gelin Luo",
  4. "title": "How to control JSON view in Actframework"
  5. }
  6. ]

我可以在Article.Service.show(String)方法上采用类似的方法来定义需要返回的字段。有人提到过如果想让前端向后端在请求中传递需要的字段该怎么办,下面是Actframework提供的方法:

show(String)方法做一点改动

  1. @GetAction("{id}")
  2. public Article show(String id) {
  3. return findById(id);
  4. }

变为

  1. @GetAction("{id}")
  2. public Article show(String id, String fields) {
  3. PropertySpec.current.set(fields);
  4. return findById(id);
  5. }

然后就可以从前端在请求中加载fields参数了:

  1. GET /article/58a6409ab6c6fe2138b67f10?fields=-tags,-content,-_created

上面的请求表示从返回JSON结果中去掉tags, content,和_created三个字段

返回结果将会是:

  1. {
  2. "id": "58a6409ab6c6fe2138b67f10",
  3. "v": 1,
  4. "language": "Java",
  5. "author": "Gelin Luo",
  6. "title": "How to control JSON view in Actframework",
  7. "_modified": "17/02/2017 11:15:22 AM",
  8. "framework": "Actframework"
  9. }

该博客的源码在码云上:

https://git.oschina.net/greenlaw110/blog_json_view_control