【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直调服务器时,是将值直接序列化为字节码,所以可以获取到值。

    @JsonProperty(
        access = Access.WRITE_ONLY
    )
    private String userPassword;
    @JsonIgnore
    private String uuid;

 

如下,为@JsonProperty内部结构。

package com.fasterxml.jackson.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonProperty {
    String USE_DEFAULT_NAME = "";
    int INDEX_UNKNOWN = -1;

    String value() default "";

    boolean required() default false;

    int index() default -1;

    String defaultValue() default "";

    JsonProperty.Access access() default JsonProperty.Access.AUTO;

    public static enum Access {
        AUTO,
        READ_ONLY,
        WRITE_ONLY,
        READ_WRITE;

        private Access() {
        }
    }
}

 

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

 

扩展知识点:

1. jackson依赖jar导入

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.1</version>
</dependency>

2. 关于jackson中@JsonIgnore@JsonProperty的说明

可参考:http://fasterxml.github.io/jackson-annotations/javadoc/2.9/com/fasterxml/jackson/annotation/JsonProperty.Access.html

3. 示例代码验证

首先,新建一个用于传参的Bean,UserTest,其中字段被@JsonProperty(分为Access.WRITE_ONLYAccess.READ_ONLY)和@JsonIgnore修饰

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class UserTest {

    private String userName;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String userPassword;

    @JsonIgnore
    private String uuid;

    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    private String readOnly;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String trans = "0";

}

其次,新建一个接口test

    @PostMapping(value = "/test")
    public String test(@RequestBody UserTest test) {
        log.info("请求参数 -->{}", JSON.toJSONString(test));
        return "success";
    }

启动服务,通过postman调用接口

 

 打印结果如下:

2020-01-25 11:57:53.450 请求参数 -->{"trans":"0","userName":"name","userPassword":"123456"}

以上,通过对结果分析,发现用postman的body体内,所设置的字段readOnly未被打印,说明在该字段未被set(说明了被READ_ONLY修饰的字段仅支持get方法)进去,而字段trans能被打印,是因为该字段有被初始化值(有初始化值的字段无论设置为READ_ONLYWRITE_ONLY修饰,都在不设置的情况下展示默认值)。

因此,总结如下:

WRITE_ONLY:仅做反序列化操作。
READ_ONLY:仅做序列化操作。

 

posted @ 2020-11-24 18:33  温柔的星空,让你感动  阅读(4371)  评论(0编辑  收藏  举报