春天HATEOAS Jackson2HalModule

时间:2017-06-07 14:22:55

标签: java spring-hateoas

假设我不想使用ResourceSupport中的spring hateoas,但我仍想使用Link

基本设置:

class A extends ResourceSupport {

}

public class B {

    private final List<Link> links = new ArrayList<>();

    @JsonProperty("links")
    public List<Link> getLinks() {
        return links;
    }
}

http方法:

@GetMapping('/a')
ResponseEntity<A> a() {
    A a = new A()

    a.getLinks().add(new Link('/api', 'index'))
    return ok(a)
}

@GetMapping('/b')
ResponseEntity<B> b() {
    B ab= new B()

    abgetLinks().add(new Link('/api', 'index'))
    return ok(b)
}

杰克逊配置:

@Primary
@Bean
Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(RelProvider relProvider, ApplicationContext applicationContext) {
    Jackson2HalModule.HalHandlerInstantiator halHandlerInstantiator = new Jackson2HalModule.HalHandlerInstantiator(
        relProvider, null, new MessageSourceAccessor(applicationContext), false
    )

    JavaTimeModule javaTimeModule = new JavaTimeModule()
    javaTimeModule.addSerializer(ZonedDateTime.class, new ZonedDateTimeSerializer(isoDateFormatter()))

    return Jackson2ObjectMapperBuilder.json()
        .handlerInstantiator(halHandlerInstantiator)
        .modules(
            new Jdk8Module(),
            new JavaTimeModule(),
            new ParameterNamesModule(JsonCreator.Mode.PROPERTIES),
            new Jackson2HalModule()
        )
        .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
        .featuresToEnable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN)
}

分别来自ab的回复:

http://localhost:8080/api/a
{
  "_links": {
    "index": {
      "href": "/api"
    }
  }
}

http://localhost:8080/api/b
{
  "links": [
    {
      "href": "/api"
    }
  ]
}

/a回复非常完美!如果没有资源支持,为什么Jackson2HalModule没有获取spring-hateoas Link列表? 我尝试了一些调试,但对杰克逊在内部决定何时使用HalLinkListDeserializer以及何时不使用时感到困惑。

1 个答案:

答案 0 :(得分:0)

试试这个:

@SpringBootApplication
@RestController
public class DemoApplication implements Jackson2ObjectMapperBuilderCustomizer {

    @Autowired
    private RelProvider relProvider;

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @GetMapping("/a")
    ResponseEntity<A> getA() {
        A a = new A();
        a.getLinks().add(new Link("/api", "index"));
        return ResponseEntity.ok(a);
    }

    @GetMapping("/b")
    ResponseEntity<B> getB() {
        B b = new B();
        b.getLinks().add(new Link("/api", "index"));
        return ResponseEntity.ok(b);
    }

    @Override
    public void customize(final Jackson2ObjectMapperBuilder mapperBuilder) {
        mapperBuilder.mixIn(B.class, BMixin.class);
        mapperBuilder.handlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, null, null));
        mapperBuilder.modulesToInstall(new Jackson2HalModule());
    }

    static class A extends ResourceSupport {
    }

    static class B {
        private final List<Link> links = new ArrayList<>();

        public List<Link> getLinks() {
            return links;
        }
    }

    static abstract class BMixin extends B {

        @Override
        @XmlElement(name = "link")
        @JsonProperty("_links")
        @JsonInclude(JsonInclude.Include.NON_EMPTY)
        @JsonSerialize(using = Jackson2HalModule.HalLinkListSerializer.class)
        @JsonDeserialize(using = Jackson2HalModule.HalLinkListDeserializer.class)
        public abstract List<Link> getLinks();

    }

}