我正在编写一个Spring Boot命令行工具,该工具应该与已经实现的API后端接口。该API后端是使用hateoas软件包以及spring数据构建的,因此会产生HAL消息类型。
在我的CLI工具中,我要发布一个包含其他实体列表(一对多关系)的实体。为了方便使用,我想在模型中使用资源类型来表达关系,并希望使用JSON序列化程序将资源转换为仅自己的href。
我的序列化程序对于一对一关系可以很好地工作,但是从不调用序列化数组或任何集合类型的方法。
这是我发布实体时API所接受的:
{
"property1": "value1","myrelation" : "http://localhohst:8080/relatedentities/1"
"mycollection": [
"http://localhost:8080/otherrelatedentities/2","http://localhost:8080/otherrelatedentities/3"
]
}
在CLI端,我在CLI应用程序中创建了一个模型实体,如下所示:
@Getter @Setter
public class MyEntity {
private String property1;
@JsonSerialize(using = HateoasResourceIdSerializer.class)
private Resource<RelatedEnity> myrelation;
@JsonSerialize(using = HateoasResourceIdSerializer.class)
private List<Resource<OtherRelatedEntity>> mycollection;
}
我写了这个HateoasResourceIdSerializer,可以将任何Resource类型转换为仅自身的href:
public class HateoasResourceIdSerializer extends StdSerializer<Resource<?>> {
private static final long serialVersionUID = 1L;
public HateoasResourceIdSerializer() {
this(null);
}
public HateoasResourceIdSerializer(Class<Resource<?>> t) {
super(t);
}
@Override
public void serialize(Resource<?> value,JsonGenerator jgen,SerializerProvider provider)
throws IOException,JsonProcessingException {
jgen.writeString(value.getId().getHref());
}
}
查看发送到API后端的有效负载,我可以看到“ myrelation”属性设置为目标实体的URL,而“ mycollection”属性始终为空。
我尝试编写第二个可以接受Collection<Resource<?>>
但没有被调用的序列化器。
我希望以上用于Resource的序列化程序将应用于数组以及任何集合类型。
编辑:
我被要求提供代码来注册序列化程序,所以就在这里。我按照以下答案之一的建议添加了两个mixin(希望我做对了),但没有看到预期的行为。我还假设由于注册,我可以从属性中删除@JsonSerialize(using = HateoasResource(s)IdSerializer.class)
注释。当前的行为是这些属性根本无法呈现。
@SuppressWarnings("deprecation")
@SpringBootApplication
@EnableHypermediaSupport(type=EnableHypermediaSupport.HypermediaType.HAL)
public class Application extends WebMvcConfigurerAdapter implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(SwissArmyKnifeApplication.class,args);
}
@Override
public void run(ApplicationArguments args) throws IllegalaccessException,IllegalArgumentException,invocationTargetException {
// ...
}
@Autowired
private HalHttpMessageConverter halHttpMessageConverter;
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(halHttpMessageConverter);
super.configureMessageConverters(converters);
}
}
@Configuration
public class HalHttpMessageConverter extends AbstractJackson2HttpMessageConverter {
public HalHttpMessageConverter() {
super(new ObjectMapper(),new MediaType("application","hal+json",DEFAULT_CHARSET));
objectMapper.registerModule(new Jackson2HalModule());
objectMapper
.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(new DefaultRelProvider(),null,null));
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
objectMapper.addMixIn(Resource.class,ResourceMixIn.class);
objectMapper.addMixIn(Resources.class,ResourcesMixIn.class);
}
@Override
protected boolean supports(Class<?> clazz) {
return ResourceSupport.class.isAssignableFrom(clazz);
}
}