Я пишу инструмент командной строки с пружинной загрузкой, который должен взаимодействовать с API-интерфейсом, который я уже реализовал. Этот API-интерфейс построен на основе данных Spring с пакетом hateoas, поэтому он генерирует типы сообщений HAL.
В моем инструменте CLI я хочу POST-объект, содержащий список других объектов (отношение один ко многим)). Для более простого использования я хотел использовать типы ресурсов в моделях для выражения отношений и иметь сериализатор JSON для преобразования ресурсов только в свои собственные hrefs.
Мой сериализатор прекрасно работает для отношений один-к-одному, но никогда не получает вызовов для сериализации массивов или любых типов коллекций.
Это то, что API принимает, когда я POST сущность:
{
"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 для преобразования любого типа ресурса в только его собственную 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" всегда равно нулю.
Iпопытался написать 2-й сериализатор, который бы принимал Collection<Resource<?>>
, но он тоже не вызывался.
Я ожидал бы, что приведенный выше сериализатор для Resource будет применяться к массивам, а также к любому типу коллекции.
РЕДАКТИРОВАТЬ: Меня попросили предоставить код для регистрации сериализаторов, так что вот оно. Я добавил два миксина, как было предложено в одном из ответов ниже (надеюсь, я все сделал правильно), но не увидел ожидаемого поведения. Я также предположил, что благодаря регистрации я смог удалить аннотацию @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);
}
}