阵列或集合类型未调用自定义序列化器

我正在编写一个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);
    }

}
abduaini83 回答:阵列或集合类型未调用自定义序列化器

您需要使用MixIn功能正确注册自定义序列化程序。除了注释属性,您还需要注释类,该类通知Jackson您要在所有情况下使用它,而不仅是MyEntity类。

创建MixIn界面:

@JsonSerialize(using = HateoasResourceIdSerializer.class)
interface ResourceMixIn {
}

并注册:

ObjectMapper mapper = JsonMapper.builder()
        .addMixIn(Resource.class,ResourceMixIn.class).build();

查看其他问题,如何在Jackson中配置Spring映射器:

,

您未包括指示如何为您的类型注册序列化程序的代码,以便提供线索。但是绝对应该为数组,CollectionMap值以及简单的属性值调用自定义序列化程序。 不需要为Collection<Type>注册单独的序列化程序(实际上有点棘手:可能,但是由于嵌套类型而需要做更多的工作),并且不打算仅仅为了支持集合中的特定类型(而是为了支持更特殊的Collection(如果有)。

因此,请包括与注册有关的代码,以及所用杰克逊的版本(如果不是最新版本,请考虑先进行升级,以确保问题仍然存在)。

本文链接:https://www.f2er.com/3131992.html

大家都在问