【fasterxml.jackson】字段反序列化问题Access.WRITE_ONLY

问题描述:

在基于Spring MVC的RESTful接口,当接口中请求参数Bean或者返回实体类的字段被@JsonProperty(access = Access.WRITE_ONLY) 约束时,通过postman调用rest接口,可以得到该字段可以值,也就是get/set是没问题的。

当通过feign接口调用时,该字段会被序列化为字节码传到所在服务的机器上,当反序列化该字段时,得到的字段值为null

原因:

被Access.WRITE_ONLY约束的字段值不会被序列化进去,所以对方获得的值为null。而postman直调服务器时,是将值直接序列化为字节码,所以可以获取到值。

解决办法:

摒弃该约束字段的Bean,新建一个Bean进行访问,调feign接口。 

具体问题案例与解决:(feign调用无法获取到用户角色roles,本身controller可以获取到)

user模块的user实体类与dto类:

package com.byx.scaffold.user.entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import com.byx.scaffold.common.entity.jpa.BaseEntity;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;

import lombok.Data;
import lombok.ToString;
import lombok.EqualsAndHashCode;

/** 用户 */
@ToString(exclude = "password")
@Data
@EqualsAndHashCode(callSuper=false)
@Entity
@Table(name = "app_user")
public class User extends BaseEntity {
	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer id;

	@Column(length = 50, unique = true, nullable = false)
	private String username;

	@Column(length = 50)
	private String name;
	/** 头像 **/
	private String avatar;
	/** 手机号码 */
	@Column(unique = true)
	private String phone;
	/** 邮箱 */
	private String email;

	/** 用户所属的组织类型(公司、政府部门) */
	private String orgType;
	/** 组织名称(可能是公司,也可能是政府部门) */
	private String orgName;

	@JsonProperty(access = Access.WRITE_ONLY )
	@Column(nullable = false)
	private String password;
	/** 账号禁用 */
	private boolean disabled;

	@JsonProperty(access = Access.WRITE_ONLY )
	@ManyToMany
	@JoinTable(name = "app_user_role", joinColumns = @JoinColumn(name= "user_id"), inverseJoinColumns = @JoinColumn(name= "role_id"))
	private List roles;

	public void replaceRoles(List roles) {
		this.roles.clear();
		if (roles != null) {
			this.roles.addAll(roles);
		}
	}

	public User() {}
	
	public User(Integer id, String username, String name) {
		this.id = id;
		this.username = username;
		this.name = name;
	}
}
package com.byx.scaffold.user.dto;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.byx.scaffold.user.entity.Role;
import com.byx.scaffold.user.entity.User;

import lombok.Data;

import javax.persistence.Column;

@Data
public class UserDTO {

	private Integer id;

	private String username;

	private String name;

	private String avatar;

	private String phone;

	private String email;
	
	private boolean disabled;
	
	private List roles;

	/** 用户所属的组织类型(公司、政府部门) */
	private String orgType;
	/** 组织名称(可能是公司,也可能是政府部门) */
	private String orgName;

	public UserDTO(User user) {
		this.id = user.getId();
		this.username = user.getUsername();
		this.name = user.getName();
		this.avatar = user.getAvatar();
		this.phone = user.getPhone();
		this.email = user.getEmail();
		this.disabled = user.isDisabled();
		this.orgType = user.getOrgType();
		this.orgName = user.getOrgName();
		Stream stream = user.getRoles().stream();
		this.roles = stream.map(r -> {
			Role role = new Role();
			role.setId(r.getId());
			role.setName(r.getName());
			return role;
		}).collect(Collectors.toList());
	}
	
	public UserDTO(String username, String name) {
		this.username = username;
		this.name = name;
	}
}
    controller类
    /**
     * 根据用户名查询用户详细信息
     * @param username
     * @return
     */
    @GetMapping("/user-by-username")
    public UserDTO getUserInfo(String username) {
        return userService.selectUserInfo(username);
    }




    serviceimpl类
   @Override
    public UserDTO selectUserInfo(String username) {
        Optional optional = userRepo.findByUsername(username);
        return optional.map(UserDTO::new).orElse(null);
    }

common公共类dto实体:

package com.byx.scaffold.common.dto;

import com.byx.scaffold.common.entity.user.Role;
import lombok.Data;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Data
public class UserDTO {

	private Integer id;

	private String username;

	private String name;

	private String avatar;

	private String phone;

	private String email;
	
	private boolean disabled;
	
	private List roles;

	/** 用户所属的组织类型(公司、政府部门) */
	private String orgType;
	/** 组织名称(可能是公司,也可能是政府部门) */
	private String orgName;

}

feign接口:

package com.byx.scaffold.context.feign;

import com.byx.scaffold.common.dto.MessageDTO;
import com.byx.scaffold.common.dto.UserDTO;
import com.byx.scaffold.common.response.BaseResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.List;

@FeignClient(value = "user")
public interface IUserFeign {

    /**
     * 根据用户名获取用户详细信息
     *
     * @return
     */
    @GetMapping("user/user/user-by-username")
    UserDTO getUserInfo(String username);
}

你可能感兴趣的:(json,json,spring,cloud)