FastJson字段解析问题

讨论了JavaBean中非public字段使用FastJson进行序列化时的问题,以及通过改变字段访问修饰符解决此问题的方法。分析了Gson与FastJson在处理非public字段时的不同行为,并强调了在使用FastJson时确保getXXX()方法与字段保持一致的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天遇到一个问题,修改一个javaBean的字段后,fastJson转换成JsonString的时候字段却没有被修改,而Gson是正常的。

JavaBean如下:

public class DistrictInfo {
    private String  province;
    private String  city;
    private String  dist;

    public DistrictInfo() {
        super();
    }

    public DistrictInfo(String province, String city, String district) {
        super();
        this.province = province;
        this.city = city;
        this.dist = district;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getDistrict() {
        return dist;
    }

    public void setDistrict(String district) {
        this.dist = district;
    }

    @Override
    public String toString() {
        return province + "," + city;
    }

}

测试类如下:


public class testJson {

    public static void main(String[] args) {

        DistrictInfo district = new DistrictInfo("陕西省", "宝鸡市", "陈仓区");
        System.out.println("FastJson: " + JSON.toJSONString(district, true));
        System.out.println("Gson: " + new Gson().toJson(district));
    }

}

运行结果如下:

FastJson: {
    "city":"宝鸡市",
    "district":"陈仓区",
    "province":"陕西省"
}
Gson: {"province":"陕西省","city":"宝鸡市","dist":"陈仓区"}

可以看到对District字段,两者解析是不同的,FastJson是错的。其实,这是FastJson的反射机制有缺陷引起的,将修饰符改为Public之后就可以正常解析了。

public class DistrictInfo {
    public String   province;
    public String   city;
    public String   dist;

    public DistrictInfo() {
        super();
    }

    public DistrictInfo(String province, String city, String district) {
        super();
        this.province = province;
        this.city = city;
        this.dist = district;
    }

}
结果:
FastJson: {
    "city":"宝鸡市",
    "dist":"陈仓区",
    "province":"陕西省"
}
Gson: {"province":"陕西省","city":"宝鸡市","dist":"陈仓区"}

如果修饰符为Protected/Private, fastJson走了一种曲线救国的方式,通过Public的getXXX()方法来获得该字段的名称和值。所以必须要保证getXXX()方法与字段XXX保持一致。如下:


public class DistrictInfo {
    private String  province;
    private String  city;
    private String  dist;

    public DistrictInfo() {
        super();
    }

    public DistrictInfo(String province, String city, String district) {
        super();
        this.province = province;
        this.city = city;
        this.dist = district;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getDist() {
        return dist;
    }

    public void setDist(String dist) {
        this.dist = dist;
    }

    @Override
    public String toString() {
        return province + "," + city;
    }

}

结果

FastJson: {
    "city":"宝鸡市",
    "dist":"陈仓区",
    "province":"陕西省"
}
Gson: {"province":"陕西省","city":"宝鸡市","dist":"陈仓区"}

结论:
fastJson在将JsonString2Obj的速度和便捷性上优于Gson,但是在Obj2JsonString时需要注意如果字段不是public的,需要注意保证getXXX()方法与字段XXX保持一致。,

### fastjson 忽略字段方法的序列化与反序列化 在使用 `fastjson` 进行 JSON 的序列化和反序列化操作时,可以通过多种方式来忽略特定字段方法。以下是具体的方式及其说明: #### 1. 使用 `@JSONField(serialize=false)` 注解 通过 `@JSONField` 注解中的 `serialize` 属性可以控制某个字段是否参与序列化。当设置为 `false` 时,该字段不会被序列化到最终的 JSON 字符串中。 ```java import com.alibaba.fastjson.annotation.JSONField; public class User { private String username; @JSONField(serialize = false) private String password; // getters and setters } ``` 在此示例中,`password` 字段将不会出现在序列化后的 JSON 中[^1]。 --- #### 2. 使用 `transient` 关键字 Java 提供了 `transient` 关键字,标记的字段会被视为临时变量,在序列化过程中会自动跳过这些字段。 ```java public class User { private String username; transient private String password; // getters and setters } ``` 这里,`password` 字段由于被声明为 `transient`,因此它不会被包含在序列化结果中[^5]。 --- #### 3. 实现自定义序列化过滤器 如果需要更加灵活地控制哪些字段应该被忽略,则可以实现 `SerializeFilter` 接口并提供自定义逻辑。 ```java import com.alibaba.fastjson.serializer.SerializeFilter; import com.alibaba.fastjson.serializer.PropertyPreFilter; import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import java.lang.reflect.Type; public class CustomFilter implements PropertyPreFilter { @Override public boolean apply(Object source, String name, Object value) { // 如果字段名为 "password" 则返回 false 表示忽略此字段 return !"password".equals(name); } } // 调用时传入过滤器 User user = new User(); System.out.println(JSON.toJSONString(user, new CustomFilter())); ``` 这种方式适用于动态决定哪些字段应被排除的情况[^3]。 --- #### 4. 配置全局序列化规则 除了针对单个类配置外,还可以通过调整 `SerializerFeature` 来影响整个项目的默认行为。例如,启用 `SkipTransientField` 特性可让所有带有 `transient` 的字段都被自动忽略。 ```java String jsonString = JSON.toJSONString(obj, SerializerFeature.SkipTransientField); ``` 这使得无需逐一手动标注即可达到一致的效果[^4]。 --- #### 5. 反序列化时忽略未知字段 对于反序列化而言,默认情况下未匹配上的额外字段会被丢弃而不会抛出异常。但如果希望显式指定某些字段不应读取回来,则可通过编写自定义解析器完成。 ```java import com.alibaba.fastjson.parser.DefaultExtJSONParser; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import java.lang.reflect.Type; public class IgnoreFieldsDeserilizer<T> implements ObjectDeserializer { @SuppressWarnings("unchecked") @Override public T deserialze(DefaultExtJSONParser parser, Type type, Object fieldName) { // 自定义逻辑... return (T)new YourClass(); // 返回对象实例 } @Override public int getFastMatchToken() { return 0; // 默认值 } } ``` 随后注册这个 Deserializer 即可生效[^4]。 --- ### 总结 以上介绍了几种常见的策略用来解决如何利用 fastjson 忽略不需要处理的数据项问题。开发者可以根据项目实际情况选择最适合自己的方案实施。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值