Backend Development 8 min read

FastJSON Serialization Mechanism: Why isChinaName() Is Invoked and How to Control Method Inclusion

This article analyzes a FastJSON serialization issue caused by an unexpected call to isChinaName(), explains the underlying JavaBeanSerializer workflow, demonstrates how ASM-generated serializers work, and proposes coding conventions using @JSONField to prevent unwanted method execution during JSON conversion.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
FastJSON Serialization Mechanism: Why isChinaName() Is Invoked and How to Control Method Inclusion

Recently a simple feature was added with an extra log line, but after deployment a flood of alerts forced a rollback. The root cause was that FastJSON invoked the isChinaName() method during serialization, where this.country was still null, leading to a NullPointerException.

Incident Review

The added log seemed harmless, yet the production alarm indicated a deeper serialization problem that required immediate investigation.

Scenario Reconstruction

A CountryDTO class was defined with a String country field, standard getters/setters, and an isChinaName() method that checks whether the country equals "中国".

public class CountryDTO {
    private String country;
    public void setCountry(String country) { this.country = country; }
    public String getCountry() { return this.country; }
    public Boolean isChinaName() { return this.country.equals("中国"); }
}

A test class serializes an instance of CountryDTO using FastJSON:

public class FastJonTest {
    @Test
    public void testSerialize() {
        CountryDTO countryDTO = new CountryDTO();
        String str = JSON.toJSONString(countryDTO);
        System.out.println(str);
    }
}

Running the test throws a NullPointerException because FastJSON calls isChinaName() while country is still null.

Source Code Analysis

Debugging shows that FastJSON generates an ASM class named ASMSerializer_1_CountryDTO to avoid reflection overhead. The serializer ultimately delegates to JavaBeanSerializer.write() , which obtains an ObjectWriter via getObjectWriter() . The critical path leads to SerializeConfig#createJavaBeanSerializer and then to TypeUtils#computeGetters .

public static List
computeGetters(Class
clazz, JSONType jsonType,
        Map
aliasMap, Map
fieldCacheMap,
        boolean sorted, PropertyNamingStrategy propertyNamingStrategy) {
    // ... omitted ...
    Method[] methods = clazz.getMethods();
    for (Method method : methods) {
        if (method.getReturnType().equals(Void.TYPE)) continue;
        if (method.getParameterTypes().length != 0) continue;
        // ... annotation handling ...
        if (methodName.startsWith("get")) { /* handle getter */ }
        if (methodName.startsWith("is")) { /* handle boolean getter */ }
    }
}

The algorithm classifies methods into three groups:

@JSONField(serialize = false, name = "xxx") annotations

Methods starting with get

Methods starting with is

Serialization Flowchart

(The original flowchart image is omitted here; it illustrates the steps from object inspection to byte‑code generation and finally to JSON output.)

Example Code

/**
 * case1: @JSONField(serialize = false)
 * case2: getXxx() returns void
 * case3: isXxx() returns non‑boolean
 * case4: @JSONType(ignores = "xxx")
 */
@JSONType(ignores = "otherName")
public class CountryDTO {
    private String country;
    public void setCountry(String country) { this.country = country; }
    public String getCountry() { return this.country; }
    public static void queryCountryList() { System.out.println("queryCountryList()执行!!"); }
    public Boolean isChinaName() { System.out.println("isChinaName()执行!!"); return true; }
    public String getEnglishName() { System.out.println("getEnglishName()执行!!"); return "lucy"; }
    public String getOtherName() { System.out.println("getOtherName()执行!!"); return "lucy"; }
    @JSONField(serialize = false)
    public String getEnglishName2() { System.out.println("getEnglishName2()执行!!"); return "lucy"; }
    public void getEnglishName3() { System.out.println("getEnglishName3()执行!!"); }
    public String isChinaName2() { System.out.println("isChinaName2()执行!!"); return "isChinaName2"; }
}

Running the test prints:

isChinaName()执行!!
getEnglishName()执行!!
{"chinaName":true,"englishName":"lucy"}

Code Standards

The serialization rules are numerous: return types, parameter counts, and annotations like @JSONType or @JSONField all affect inclusion. To reduce variance among team members, it is recommended to explicitly mark non‑serializable methods with @JSONField(serialize = false) .

public class CountryDTO {
    private String country;
    public void setCountry(String country) { this.country = country; }
    public String getCountry() { return this.country; }
    @JSONField(serialize = false)
    public static void queryCountryList() { System.out.println("queryCountryList()执行!!"); }
    public Boolean isChinaName() { System.out.println("isChinaName()执行!!"); return true; }
    public String getEnglishName() { System.out.println("getEnglishName()执行!!"); return "lucy"; }
    @JSONField(serialize = false)
    public String getOtherName() { System.out.println("getOtherName()执行!!"); return "lucy"; }
    @JSONField(serialize = false)
    public String getEnglishName2() { System.out.println("getEnglishName2()执行!!"); return "lucy"; }
    @JSONField(serialize = false)
    public void getEnglishName3() { System.out.println("getEnglishName3()执行!!"); }
    @JSONField(serialize = false)
    public String isChinaName2() { System.out.println("isChinaName2()执行!!"); return "isChinaName2"; }
}

High‑Frequency Serialization Scenarios

(Another diagram shows the three most common cases where serialization triggers unexpected method calls.)

The overall process follows: discover the issue → analyze the principle → solve the problem → elevate to coding standards.

Business side: solve the problem, choose a good solution, and extend it to multiple systems.

Technical side: master the underlying principle of each isolated issue.

Backend DevelopmentfastjsonJava SerializationJSONFieldJava Bean
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.