org.springframework.http.converter.HttpMessageNotWritableException...解决方法
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
项目场景
在进行在线使用Spring Security
做为权限框架的办公系统的个人项目开发中控制台输出的错误信息为无法写入JSON的错误遇到了这个比较让人摸不着头脑的问题我想应该不局限于当前项目场景将目前遇到这种错误的解决方法进行记录如果以后再遇到相同的错误有不同解决方法时再回来记录。
问题描述
要实现的功能是获取管理员列表向后端传递的参数和数据库中想要查询的内容也可以正常的获取到但是在将查询到的数据返回到前端时就出现了报错
Swagger调试的内容如下
从控制台的截图可以看到数据库中的数据正常返回以及前端传递的参数正常接收
控制台报错如下
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: A granted authority textual representation is required; nested exception is com.fasterxml.jackson.databind.JsonMappingException: A granted authority textual representation is required (through reference chain: java.util.ArrayList[0]->net.csdn.server.pojo.Admin["authorities"])]
将问题进行翻译后可以知道内容为
[org.springframework.http.converter.HttpMessageNotWritableException无法写入 JSON需要授予权限的文本表示 嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException需要授予权限的文本表示通过引用链java.util.ArrayList[0]->net.csdn.server.pojo.Admin[“authorities”] ]
原因分析
出现了这种问题首先可以在控制台中看到是Admin
类中的某个字段需要授予权限因此问题就在于Admin
类中的字段上首先能够想到考虑以下几点 项目中引入了lombok
同时Admin
类实现了UserDetails
接口
lombok
的@Data
注解没有加上导致某些字段没有getter
以及setter
方法- 对于
Spring Security
中UserDetails
的接口字段有一些是不需要返回给前端的
对应的Admin
类代码如下
package net.csdn.server.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
*
* </p>
*
* @author zhangrongkang
* @since 2022-01-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_admin")
@ApiModel(value="Admin对象", description="")
public class Admin implements Serializable, UserDetails {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "手机号码")
private String phone;
@ApiModelProperty(value = "住宅电话")
private String telephone;
@ApiModelProperty(value = "联系地址")
private String address;
@ApiModelProperty(value = "是否启用")
private Boolean enabled;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "用户头像")
private String userFace;
@ApiModelProperty(value = "备注")
private String remark;
@ApiModelProperty(value = "角色")
@TableField(exist = false)
private List<Role> roles;
/**
* 通过角色名获取到对应的权限
*
* @return 与角色名对应的权限集合
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = roles
.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
}
可以看到在Admin
类中是有@Data
注解的因此排除第一种可能的情况。对于第二种情况来说发现重写的getAuthorities
方法中返回的authorities
与控制台中的报错字段一致因此可以将问题缩小至前端不需要将authorities
进行返回
解决方案
在当前Admin
类中的getAuthorities
方法上添加@JsonIgnore
注解将getAuthorities
方法返回的内容不出现在返回结果中
在添加该注解后代码正常运行
总结
无法将JSON
返回到前端有很多原因这里的解决方法是对UserDetails
的实现类中的方法添加注解表示其返回到内容不需要返回到前端。对@JsonIgnore
注解的使用进行一个小的总结
- 作用在
JSON
序列化时将Java Bean
中的⼀些属性忽略掉序列化和反序列化都受影响 - 使⽤场景⼀般标记在属性或者⽅法上返回的
Json
数据即不包含该属性