- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
Level 3例如,RESTful API 的功能自定义媒体类型,如 application/vnd.service.entity.v1+json
。在我的情况下,我使用 HAL在我的 JSON 中提供相关资源之间的链接。
我不清楚使用 HAL+JSON 的自定义媒体类型的正确格式。我目前拥有的看起来像 application/vnd.service.entity.v1.hal+json
。我最初使用 application/vnd.service.entity.v1+hal+json
,但 +hal
后缀未注册,因此违反了 section 4.2.8 of RFC6838 .
现在 Spring HATEOAS 支持开箱即用的 JSON 链接,但对于 HAL-JSON,您需要使用 @EnableHypermediaSupport(type=EnableHypermediaSupport.HypermediaType.HAL)
。就我而言,因为我使用的是 Spring Boot,所以我将它附加到我的初始化程序类(即扩展 SpringBootServletInitializer
的类)。但是 Spring Boot 不会立即识别我的自定义媒体类型。因此,为此,我必须弄清楚如何让它知道它需要对 application/vnd.service.entity.v1.hal+json
形式的媒体类型使用 HAL 对象映射器>.
对于我的第一次尝试,我在 Spring Boot 初始化程序中添加了以下内容:
@Bean
public HttpMessageConverters customConverters() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "json", Charset.defaultCharset()),
new MediaType("application", "*+json", Charset.defaultCharset()),
new MediaType("application", "hal+json"),
new MediaType("application", "*hal+json")
));
CurieProvider curieProvider = getCurieProvider(beanFactory);
RelProvider relProvider = beanFactory.getBean(DELEGATING_REL_PROVIDER_BEAN_NAME, RelProvider.class);
ObjectMapper halObjectMapper = beanFactory.getBean(HAL_OBJECT_MAPPER_BEAN_NAME, ObjectMapper.class);
halObjectMapper.registerModule(new Jackson2HalModule());
halObjectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider));
converter.setObjectMapper(halObjectMapper);
return new HttpMessageConverters(converter);
}
这行得通,我正在以正确的 HAL 格式获取链接。然而,这是巧合。这是因为最终被报告为与 application/vnd.service.entity.v1.hal+json
“兼容”的实际媒体类型是 *+json
;它不能针对 application/*hal+json
识别它(请参阅后面的解释)。我不喜欢这个解决方案,因为它污染了现有的 JSON 转换器,担心 HAL。所以,我做了一个不同的解决方案:
@Configuration
public class ApplicationConfiguration {
private static final String HAL_OBJECT_MAPPER_BEAN_NAME = "_halObjectMapper";
@Autowired
private BeanFactory beanFactory;
@Bean
public HttpMessageConverters customConverters() {
return new HttpMessageConverters(new HalMappingJackson2HttpMessageConverter());
}
private class HalMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public HalMappingJackson2HttpMessageConverter() {
setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "hal+json"),
new MediaType("application", "*hal+json")
));
ObjectMapper halObjectMapper = beanFactory.getBean(HAL_OBJECT_MAPPER_BEAN_NAME, ObjectMapper.class);
setObjectMapper(halObjectMapper);
}
}
}
此解决方案不起作用;我最终在我的 JSON 中获得了不符合 HAL 的链接。这是因为 application/vnd.service.entity.v1.hal+json
被 application/*hal+json
识别不。发生这种情况的原因是检查媒体类型兼容性的 MimeType
仅将以 *+
开头的媒体类型识别为子类型的有效通配符媒体类型(例如,application/*+json
)。这就是第一个解决方案奏效的原因(巧合)。
所以这里有两个问题:
MimeType
将从不识别 application/vnd.service.entity.v1.hal+json
形式的供应商特定 HAL 媒体类型> 针对application/*hal+json
.MimeType
将识别格式为 application/vnd.service.entity.v1+hal+json
的供应商特定 HAL 媒体类型针对 application/*+hal+json
,然而 根据 section 4.2.8 of RFC6838,这些是无效的 mimetypes .似乎唯一的正确方法是如果 +hal
被识别为有效后缀,在这种情况下,上面的第二个选项就可以了。否则,任何其他类型的通配符媒体类型都无法专门识别供应商特定的 HAL 媒体类型。唯一的选择是用 HAL 问题覆盖现有的 JSON 消息转换器(参见第一个解决方案)。
目前的另一种解决方法是在为消息转换器创建支持的媒体类型列表时指定您正在使用的每个自定义媒体类型。那就是:
@Configuration
public class ApplicationConfiguration {
private static final String HAL_OBJECT_MAPPER_BEAN_NAME = "_halObjectMapper";
@Autowired
private BeanFactory beanFactory;
@Bean
public HttpMessageConverters customConverters() {
return new HttpMessageConverters(new HalMappingJackson2HttpMessageConverter());
}
private class HalMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
public HalMappingJackson2HttpMessageConverter() {
setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "hal+json"),
new MediaType("application", "vnd.service.entity.v1.hal+json"),
new MediaType("application", "vnd.service.another-entity.v1.hal+json"),
new MediaType("application", "vnd.service.one-more-entity.v1.hal+json")
));
ObjectMapper halObjectMapper = beanFactory.getBean(HAL_OBJECT_MAPPER_BEAN_NAME, ObjectMapper.class);
setObjectMapper(halObjectMapper);
}
}
}
这样做的好处是不会污染现有的 JSON 转换器,但看起来不够优雅。有谁知道正确的解决方案?我是不是完全错了?
最佳答案
虽然这个问题有点老了,但我最近偶然发现了同样的问题,所以我想把我的 2 美分献给这个话题。
我认为这里的问题是对 HAL 对 JSON 的理解。正如您已经指出的 here ,所有 HAL 都是 JSON,但并非所有 JSON 都是 HAL。根据我的理解,两者之间的区别在于,HAL 为语义/结构定义了一些约定,例如告诉您在 _links
之类的属性后面您会找到一些链接,而 JSON 只定义了格式像 key: [value]
(正如@zeroflagL 已经提到的)
这就是为什么媒体类型被称为application/hal+json
的原因。它基本上说它是 JSON 格式的 HAL 样式/语义。这也是存在媒体类型application/hal+xml
(source )的原因。
现在使用供应商特定的媒体类型,您可以定义自己的语义,因此您可以替换 application/hal+json
中的 hal
并且不要扩展它。
如果我的理解正确,您基本上想说您有一个自定义媒体类型,它使用 HAL 样式作为 JSON 格式。 (这样,客户端可以使用一些 HAL 库来轻松解析您的 JSON。)
所以,最后我认为您基本上必须决定是否要区分 JSON 和基于 HAL 的 JSON,以及您的 API 是否应该提供其中之一或两者。
如果您想同时提供两者,则必须定义两种不同的媒体类型 vnd.service.entity.v1.hal+json
和 vnd.service.entity.v1+ json
。对于 vnd.service.entity.v1.hal+json
媒体类型,您必须添加自定义 MappingJackson2HttpMessageConverter
使用 _halObjectMapper
返回基于 HAL 的 JSON,而默认支持 +json
媒体类型,以良好的旧 JSON 返回您的资源。
如果您总是想提供基于 HAL 的 JSON,则必须启用 HAL 作为默认 JSON-Media 类型(例如,通过添加支持 +json 的自定义
媒体类型并使用前面提到的 MappingJackson2HttpMessageConverter
_halObjectMapper
),因此对 application/vnd.service.entity.v1+json
的每个请求都由返回 HAL 的转换器处理- 基于 JSON。
在我看来,我认为正确的方法是仅区分 JSON 和其他格式(如 XML),并且在您的媒体类型文档中您会说,您的 JSON 在某种程度上是受 HAL 启发的客户端可以使用 HAL 库来解析响应。
编辑:
要绕过您必须单独添加每个供应商特定媒体类型的问题,您可以覆盖 isCompatibleWith您要添加到自定义 MappingJackson2HttpMessageConverter
converter.setSupportedMediaTypes(Arrays.asList(
new MediaType("application", "doesntmatter") {
@Override
public boolean isCompatibleWith(final MediaType other) {
if (other == null) {
return false;
}
else if (other.getSubtype().startsWith("vnd.") && other.getSubtype().endsWith("+json")) {
return true;
}
return super.isCompatibleWith(other);
}
}
));
关于java - 由于 HAL+JSON 媒体类型不明确,无法使用 Spring HATEOAS 执行 HAL+JSON Level 3 RESTful API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27494779/
我在 linux 上工作。我对windows没有太多想法。 windows中文件的权限是如何组织的?我们在unix中是否有像chmod这样的api来更改权限? 最佳答案 对于 Windows,有一个名
应用程序编程接口(interface) (API) 是一组用于访问基于 Web 的软件应用程序的编程指令和标准。 如果出现 ,有人可以向我解释一下吗?谷歌地图 或 优酷 这是API哪个是softwar
我有两个应用程序,A 和 B,它们使用 android 库 C。B 有一个服务 A 想通过 C 使用,例如 在我的库中有一个类试图将它绑定(bind)到服务,
我正在正常或安全模式下启动相机应用程序,具体取决于使用我的应用程序执行的手势,但一旦用户选择应用程序并点击始终,则没有选项可以更改默认值,即使是从 Android 的设置菜单中也是如此. camera
我有一个数据集,本质上是一个稀疏二进制矩阵,表示两个集合的元素之间的关系。例如,让第一组是人(用他们的名字表示),例如像这样的东西: people = set(['john','jane','mike
何为pythonic? pythonic如果翻译成中文的话就是很python。很+名词结构的用法在中国不少,比如:很娘,很国足,很CCTV等等。 我的理解为,很+名词表达了一种特殊和强调的意味。
某些 Prolog 目标的确定性成功问题已经一次又一次地出现在 - 至少 - 以下问题: Reification of term equality/inequality Intersection an
我指的是 DateTime.TryParse(string s, out DateTime result) 重载,它尝试从字符串中解析 DateTime - 没有特定的格式正在指定。 我可以从http
2020 年 04 月 10 日,《中共中央国务院关于构建更加完善的要素市场化配置体制机制的意见》正式公布,将数据确立为五大生产要素(土地、资本、劳动力以及技术)之
有人可以解释一下 NSNotification 的 addObserver 函数中 notificationSender 的用途吗? 这是 Apple 文档的解释: notificationSende
我是一名优秀的程序员,十分优秀!