2
头图
In front of the source code, there is no secret.
Hello everyone, I am the representative of the Java class. For more information about Java, please follow the public : 160f635318e130 Java class representative .

"Ali Development Specification Taishan Edition" (2020.04.22)-->Programming Protocol-->(1) Naming Style-->Article 8 stipulates:

[Mandatory] Do not add the is prefix to any boolean variables in the POJO class, otherwise partial frame analysis will cause serialization errors.

Regarding such a [mandatory] level of regulation, although a simple description is made in the specification, it still appears very inconspicuous, so that even though I am familiar with the specification, I still stepped on this pit.

0 Cause

Recently, I wrote a DingTalk alert tool class. For this task with clear requirements and clear development documents, I wrote the code at my fingertips and finished it quickly.

However, during the self-test, I found that @ all this interface could not pass the unit test. After some tracking, I finally found the reason, so I have this article.

1 Reproduce the problem

Sending a Dingding message is a post request, and Dingding is endorsed by Ali. If the call fails, it is naturally a problem for me as a developer.

The following is the interface description of isAtAll , and the parameter 060f635318e255 indicates whether or not @ all

{
    "msgtype": "text", 
    "text": {
        "content": "我就是我, 是不一样的烟火@156xxxx8827"
    }, 
    "at": {
        "atMobiles": [
            "156xxxx8827", 
            "189xxxx8325"
        ], 
        "isAtAll": false
    }
}

According to this json string, I wrote the following POJO class corresponding to it, and used fastjson for json serialization

public class Message {
    /**
     * 消息类型
     **/
    private String msgtype = "text";
    /**
     * 消息内容对象
     **/
    private Text text;
    /**
     * 被@对象
     **/
    private At at;

    public static class At{
        /**
         * 被@人电话
         **/
        private List<String> atMobiles;

        /**
         * 是否@所有人
         **/
        private boolean isAtAll;
        // 省略getter、setter
        }
    // 省略无关代码...
}

The problem lies in private boolean isAtAll; . Have you found that this parameter of Ali violates the development specifications mentioned at the beginning? After serialization using fastjson, this property is actually converted to:

"atAll": true

This cheating, eat the previous is! Can not be @everyone

2 Tracing to the source

Why did you eat is after serialization? With this question, I tracked the source code of fastjson and found that when serializing, it uses the getter method name of the property, and the automatically generated getter and setter of the isAtAll

public boolean isAtAll() {
    return isAtAll;
}

public void setAtAll(boolean atAll) {
    isAtAll = atAll;
 }

The corresponding processing of method names in fastjson is in com.alibaba.fastjson.util.TypeUtils.computeGetters . The source code is excerpted as follows:

if(methodName.startsWith("is")){
    if(methodName.length() < 3){
        continue;
    }
    if(method.getReturnType() != Boolean.TYPE
            && method.getReturnType() != Boolean.class){
        continue;
    }
    String propertyName;
    Field field = null;
    if(Character.isUpperCase(c2)){
        if(compatibleWithJavaBean){
            propertyName = decapitalize(methodName.substring(2));
        } else{
            propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3);
        }
        propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName, 2);
    }

In other words, for the method starting with is, fastjson first intercepts the third character, if the character is uppercase, it is converted to lowercase, and the remaining method names are assembled to form the attribute name.

For example: The attribute name assembled by the isAtAll atAll , and the final result is to put our is
Let's eat it!

3 solution

Now that the root cause of the problem has been found, we only need to prescribe the right medicine. For different application scenarios, the class representative will summarize three solutions for everyone:

  1. For code with modification permission, strictly abide by the development specifications. Do not is at the beginning, if there is, change it
  2. For third-party interfaces, there are parameters like isXXX in the parameters. You can use fastjson's @JSONField(name = "anotherName") on the corresponding attribute field to customize the attribute name
  3. You can manually modify the getter and setter method names

4 Extension

SpringBoot integrates jackson and uses jackson for json serialization by default. After testing, jackson also eats is . The principle is similar to fastjson, so I won’t explain too much. During the development process, follow the solution mentioned in the article. can

reference

  • fastjson source code
  • "Ali Development Specification Taishan Edition" (2020.04.22)

[Recommended reading]
RabbitMQ tutorial
uses Spring Validation to elegantly validate parameters
Freemarker Tutorial (1)
Dubbo exception handling source code exploration and best practices
downloaded attachment names are always garbled? You should read the RFC document!
MySQL priority queue in a simple way (the order by limit problem you will definitely step on)


The codeword is not easy, welcome to like, follow and share.
Search: [Java class representative], follow the official account, update every day, and get more Java dry goods in time.


Java课代表
640 声望1k 粉丝

JavaWeb一线开发,5年编程经验