单个对象的Spring HATEOAS链接以HAL格式返回,而对象数组则遵循规范格式。

4

我正在使用Spring HATEOAS 0.20(也尝试过0.23),当返回单个对象与返回对象数组时,出现了非常奇怪的行为。当返回单个对象时,生成的JSON会返回按照HAL规范格式化的HATEOAS链接(即"_links"),而我不希望这样。

{
  "_Id": 161,
  ...
  "_links": {
    "self": {
      "href": "http://localhost:8080/library/161"
    }
  }
}

在返回对象数组时,生成的 JSON 以规范格式返回 HATEOAS 链接(即“links”),这正是我所需要的。

[
  {
    "_Id": 277,
    ...
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/library/277"
      }
    ]
  }
]

我没有指定@EnableHypermediaSupport,所以不应该支持HAL。但是,当返回单个对象时,我仍然得到了HAL格式。

有人知道这是为什么吗?如何按照HATEOAS规范返回带有HATEOAS链接的单个对象?

===== 根据请求添加更多信息的更新 =====

如果使用以下代码返回JSON负载,则会获得HAL链接:

//
//------------------- Get Single Membership As Single Object ----------------------------------------------
//
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = REQUEST_GET_MEMBERSHIP, method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<MembershipResource> getMembership(@PathVariable("membership-id") Integer membershipId) {
    Membership membership = membershipRepository.findOne(membershipId);

    if (membership == null) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("error", "Membership with ID of " + membershipId + " does not exist.");
        return new ResponseEntity<MembershipResource>(headers, HttpStatus.NOT_FOUND);
    }

    MembershipResourceAssembler assm = new MembershipResourceAssembler();
    MembershipResource membershipResource = assm.toResource(membership);

    System.out.println("membership id: " + membership.getId());
    return new ResponseEntity<MembershipResource>(membershipResource, HttpStatus.OK);
}

以上将生成HAL规范风格的链接:
{
  "_Id": 277,
  "member": {
    "_Id": 112,
    "title": "Mr.",
    "firstName": "ABC",
    "middleName": "",
    "lastName": "XYZ",
    "active": true,
    "_links": {
      "self": {
        "href": "http://localhost:8080/members/112"
      }
    }
  },
  "membershipTermType": "2016",
  "card": {
    "_Id": 27,
    "name": "27",
    "graphicUrl": "",
    "number": 27,
  },
  "active": false,
  "paid": true,
  "renewal": true,
  "termsAndConditionsAcknowledged": true,
  "_links": {
    "self": {
      "href": "http://localhost:8080/memberships/277"
    }
  }
}

如果我修改方法以返回单个成员的列表,则返回的JSON负载将具有HATEOAS规范链接:

//
//------------------- Get Single Membership As List --------------------------------------------------------
//
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = REQUEST_GET_MEMBERSHIP, method = RequestMethod.GET,  produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<List<MembershipResource>> getMembership(@PathVariable("membership-id") Integer membershipId) {
    Membership membership = membershipRepository.findOne(membershipId);

    if (membership == null) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("error", "Membership with ID of " + membershipId + " does not exist.");
        return new ResponseEntity<List<MembershipResource>>(headers, HttpStatus.NOT_FOUND);
    }

    MembershipResourceAssembler assm = new MembershipResourceAssembler();
        MembershipResource membershipResource = assm.toResource(membership);

    ArrayList<MembershipResource> list = new ArrayList<MembershipResource>();
    list.add(membershipResource);

    System.out.println("membership id: " + membership.getId());
    return new ResponseEntity<List<MembershipResource>>(list, HttpStatus.OK);
}

上述内容将生成符合HATEOAS规范的链接:
[
  {
    "_Id": 277,
    "member": {
      "_Id": 112,
      "title": "Mr.",
      "firstName": "ABC",
      "middleName": "",
      "lastName": "XYZ",
      "active": true,
      "links": [
        {
          "rel": "self",
          "href": "http://localhost:8080/members/112"
        }
      ]
    },
    "membershipTermType": "2016",
    "card": {
      "_Id": 27,
      "name": "27",
      "graphicUrl": "",
      "number": 27,
      "links": []
    },
    "active": false,
    "renewal": true,
    "paid": true,
    "termsAndConditionsAcknowledged": true,
    "links": [
      {
        "rel": "self",
        "href": "http://localhost:8080/memberships/277"
      }
    ]
  }
]

有人知道为什么会发生这种情况吗? 按照HATEOAS规范返回带有HATEOAS链接的单个对象需要做些什么?


当您请求时,您会得到HAL。您的请求是什么样子的?以及您的控制器方法呢? - a better oliver
@zeroflagL - 我修改了我的帖子来回答你的问题。谢谢! - shermantech
不同的行为很可能源于一个实例返回了ResourceSupport,而另一个实例没有(只返回了一个List)。你使用Spring Boot吗? - a better oliver
是的,我目前正在使用Spring Boot。 - shermantech
然后您可以尝试在应用程序中添加@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class)或在属性文件中添加spring.hateoas.use-hal-as-default-json-media-type=false - a better oliver
@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class) 做到了!感谢 @zeroflagL - shermantech
1个回答

3

由于我正在使用Spring Boot作为我的应用程序服务器,@zeroflagL建议我尝试在应用程序中添加@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class)或在属性文件中添加spring.hateoas.use-hal-as-default-json-media-type=false

在我的应用程序类中添加配置注释@EnableAutoConfiguration(exclude = HypermediaAutoConfiguration.class)解决了问题。


我无法在Spring Boot 1.4.3.RELEASE中使其工作。有什么想法吗? - Alex White
@AlexWhite 将 @RequestMapping(value = "/someresource", produces ={"application/collection+json" } ) 添加到控制器似乎可以解决问题。 - LivePwndz

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