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<FieldInfo> computeGetters(Class<?> clazz, JSONType jsonType,
        Map<String,String> aliasMap, Map<String,Field> 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.