likes
comments
collection
share

JsonIgnore误用引发的对象绑定问题

作者站长头像
站长
· 阅读数 24

问题描述

Comment

开发通用评论功能时,建立评论实体。

/**
 * @author zhangxishuo on 2018/8/19
 * 评论实体
 */
@Entity
@ApiModel(value = "Comment (评论)", description = "评论实体")
public class Comment extends YunZhiAbstractEntity {

    private static final Map<String, Class<?>> serviceMap = new HashMap<>();

    static {
        serviceMap.put("NonMandatoryInstrumentCheckApplyService", NonMandatoryInstrumentCheckApplyService.class);
    }

    @Column(length = 3000)
    private String content;

    @Transient    // 该字段不映射到数据库
    @JsonIgnore   // 序列化时忽略属性
    private String serviceName;

    @Transient    // 该字段不映射到数据库
    @JsonIgnore   // 序列化时忽略属性
    private Long relationId;
}

这里因为考虑到需要将信息传递给相关联该评论的实体,所以建了两个额外的属性serviceNamerelationId,但是这个仅在Service中使用,并不映射到数据库,同时也不希望这个字段映射到前台是也显示。

测试代码

@Test
public void saveTest() throws Exception {
    logger.debug("测试数据");
    NonMandatoryInstrumentCheckApply nonMandatoryInstrumentCheckApply = nonMandatoryInstrumentCheckApplyService.getOneSavedObject();
    Long relationId = nonMandatoryInstrumentCheckApply.getId();
    String content = "测试评论";
    String serviceName = "NonMandatoryInstrumentCheckApplyService";

    logger.debug("生成评论");
    Comment comment = new Comment();
    comment.setRelationId(relationId);
    comment.setContent(content);
    comment.setServiceName(serviceName);

    String json = JSONObject.toJSONString(comment);

    this.mockMvc
            .perform(MockMvcRequestBuilders.post("/Comment")
            .content(json)
            .contentType(MediaType.APPLICATION_JSON_UTF8))
            .andDo(document("Comment_save", preprocessResponse(prettyPrint())))
            .andExpect(MockMvcResultMatchers.status().isOk());
}

看着好像没什么问题,但是执行时发生了错误,Required type must not be null

JsonIgnore误用引发的对象绑定问题

logger.debug("获取服务Bean");
String serviceName = comment.getServiceName();
Class<?> className = Comment.getServiceMap().get(serviceName);
Object service = ContextConfig.getContext().getBean(className);

在调用getBean(Class<T> requiredType)动态获取Bean的时候,抛出了异常,requiredType不能为空,也就是我们调用getBean传的参数className是空。

调试

Debug

开启找Bug模式,我们看我们测试请求的字符串json是没问题,属性齐全。

JsonIgnore误用引发的对象绑定问题

走到控制器时,这两个属性就没了。结论:Json反序列化时出错。

JsonIgnore误用引发的对象绑定问题

JsonIgnore误用引发的对象绑定问题

JsonIgnore

原因就在@JsonIgnore上,我只考虑了后台的对象序列化到前台时需要忽略该属性,从而添加了这个注解。

但是这个注解是在序列化与反序列化时都生效的,也就是说:序列化时,忽略该属性;反序列化时,也忽略该属性。所以造成了绑定时@JsonIgnore标注的属性为null的结果。

解决

去掉@JsonIgnore注解,一切正常。

总结

记得第一次见到@JsonIgnore注解时去网上查这个注解时干什么的。

JsonIgnore误用引发的对象绑定问题

JsonIgnore误用引发的对象绑定问题

谷歌第一条。然后,没有认真看,一直以为是JsonIgnore只在对象序列化为json是才起作用。导致了误用。

JsonIgnore在序列化与反序列化时都生效!

一知半解,害己误人。