【发布时间】:2018-12-26 07:51:06
【问题描述】:
tldr; 我想在使用 Jackson @JsonAppend 将 JPA 实体序列化为 JSON 时添加虚拟字段。虚拟字段的值必须通过 Spring 管理的服务来确定。如何在 Jackson 类中注入我的 Spring 管理服务?
技术:Spring Boot 1.5.10、Spring Data Rest、JPA 2.1、Jackson 2.8.10
详情:
我有一个 Spring Data 托管的 JPA 实体:
@Entity
public class Stream {
...
}
我使用 Mixin 创建了一个自定义 Jackson 模块,以添加 @JsonAppend 虚拟字段,如下所示:
@Bean
public Module customModule() {
return new CustomModule();
}
@Component
class CustomModule extends SimpleModule {
CustomModule() {
setMixInAnnotation(Stream.class, StreamMixin.class);
}
@JsonAppend(
props = {
@JsonAppend.Prop(name = "canEdit", value = ABACInspector.class)
}
)
abstract class StreamMixin {}
}
ABACInspector 类扩展了 Jackson 的 VirtualBeanPropertyWriter 以确定虚拟字段 canEdit 的值。如果此类不使用 Spring 服务(例如设置硬编码值),它可以正常工作,并且该字段显示在 REST API JSON 响应中。但是自动装配 Spring bean 不起作用,对象仍然是 null。
@Component
class ABACInspector extends VirtualBeanPropertyWriter {
@Autowired
private PermissionEvaluator permissionEvaluator;
public ABACInspector() {
}
public ABACInspector(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) {
super(propDef, contextAnnotations, declaredType);
}
@Override
protected Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
boolean permission = permissionEvaluator.hasPermission(authentication, bean, Action.STREAM_VIEW);
System.out.println("evaluated permission is " + permission);
return permission;
}
@Override
public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) {
return new ABACInspector(propDef, null, type);
}
}
下面是 NPE 错误(因为permissionEvaluator 从未注入):
{"status":"INTERNAL_SERVER_ERROR","message":"Could not write JSON:
(was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException:
(was java.lang.NullPointerException) (through reference chain: org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer$1[\"content\"]->com.example.streammanagement.Stream[\"canView\"])"
我知道 Spring Data Rest 的 HalHandlerInstantiator 包含 AutowireCapableBeanFactory,但我不确定这如何/是否可以提供帮助。参考DATAREST-840
【问题讨论】:
标签: spring spring-mvc spring-boot jackson spring-data-rest