【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:僅做序列化操作。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM