当前位置: 首页 > news >正文

FastJson系列化使用toJSONString时null值问题

FastJson系列化使用toJSONString时null值问题

  • 问题描述
  • 问题分析
  • 解决方法:

问题描述

在使用fastjson调用

JSON.toJSONString(JSON.parseObject(demo), features);

fastJson包版本

  <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.53</version>
  </dependency>

方法将一个String转换成一个对象时,如果对象obj的属性字段有值为null时,该字段会被系列化成"";

传入String对象:

{
    "code": "SUCCESS",
    "data": {
        "amount_of_handling_fees": null,
        "associate_amount": 200000,
        "associate_currency": "VND",
        "associate_risk_review_id": "",
        "client_rate": "1.0000000000000000",
        "credited_amount": null,
        "fx_order_no": "",
        "goods_tax": null,
        "incoming_payment_id": "SZLS2025021011112568049767730",
        "merchant_order_list": [
            {
                "merchant_order_no": "1889223743019364353",
                "order_associate_amount": 200000,
                "order_associate_amount_goods": null,
                "order_associate_amount_service": null,
                "order_currency": "VND",
                "order_goods_tax": null,
                "order_service_tax": null,
                "trade_order_no": "MYDD2025021116124303299021"
            }
        ],
        "order_associated_id": "AS202502111632520283768844",
        "risk_review_remark": "",
        "risk_review_type": "",
        "service_tax": null,
        "status": "processing",
        "tax_amount": null,
        "unsettlement_amount": 200000,
        "unsettlement_currency": "VND"
    },
    "message": "success",
    "timestamp": "2025-02-12T11:16:13+08:00"
}

使用系列化后

String sortedJson = JSON.toJSONString( parseObject(demo));
{
    "code": "SUCCESS",
    "data": {
        "associate_amount": 200000,
        "associate_currency": "VND",
        "associate_risk_review_id": "",
        "client_rate": "1.0000000000000000",
        "fx_order_no": "",
        "incoming_payment_id": "SZLS2025021011112568049767730",
        "merchant_order_list": [
            {
                "merchant_order_no": "1889223743019364353",
                "order_associate_amount": 200000,
                "order_currency": "VND",
                "trade_order_no": "MYDD2025021116124303299021"
            }
        ],
        "order_associated_id": "AS202502111632520283768844",
        "risk_review_remark": "",
        "risk_review_type": "",
        "status": "processing",
        "unsettlement_amount": 200000,
        "unsettlement_currency": "VND"
    },
    "message": "success",
    "timestamp": "2025-02-12T11:16:13+08:00"
}

问题描述:
我们可以很明显的看到系列化后null已经修改成""

问题分析

其实fastjson的toJSONString()。

源码分析:
com.alibaba.fastjson.JSON

 public static String toJSONString(Object object) {
        JSONWriter.Context context = createWriteContext(SerializeConfig.global, DEFAULT_GENERATE_FEATURE);
        try (JSONWriter writer = JSONWriter.of(context)) {
            if (object == null) {
                writer.writeNull();
            } else {
                writer.setRootObject(object);
                Class<?> valueClass = object.getClass();
                ObjectWriter objectWriter = context.getObjectWriter(valueClass, valueClass);
                objectWriter.write(writer, object, null, null, 0);
            }

            return writer.toString();
        } catch (com.alibaba.fastjson2.JSONException ex) {
            Throwable cause = ex.getCause() != null ? ex.getCause() : ex;
            throw new JSONException(ex.getMessage(), cause);
        } catch (RuntimeException ex) {
            throw new JSONException("toJSONString error", ex);
        }
    }

com.alibaba.fastjson.JSON

 static {
        int features = 0;
        features |= SerializerFeature.QuoteFieldNames.getMask();
        features |= SerializerFeature.SkipTransientField.getMask();
        features |= SerializerFeature.WriteEnumUsingName.getMask();
        features |= SerializerFeature.SortField.getMask();

        DEFAULT_GENERATE_FEATURE = features;
    }
public static JSONWriter.Context createWriteContext(
            SerializeConfig config,
            int featuresValue,
            SerializerFeature... features
    ) {
        for (SerializerFeature feature : features) {
            featuresValue |= feature.mask;
        }

        ObjectWriterProvider provider = config.getProvider();
        provider.setCompatibleWithFieldName(TypeUtils.compatibleWithFieldName);

        JSONWriter.Context context = new JSONWriter.Context(provider);

        if (config.fieldBased) {
            context.config(JSONWriter.Feature.FieldBased);
        }

        if (config.propertyNamingStrategy != null
                && config.propertyNamingStrategy != PropertyNamingStrategy.NeverUseThisValueExceptDefaultValue
                && config.propertyNamingStrategy != PropertyNamingStrategy.CamelCase1x
        ) {
            NameFilter nameFilter = NameFilter.of(config.propertyNamingStrategy);
            configFilter(context, nameFilter);
        }

        if ((featuresValue & SerializerFeature.DisableCircularReferenceDetect.mask) == 0) {
            context.config(JSONWriter.Feature.ReferenceDetection);
        }

        if ((featuresValue & SerializerFeature.UseISO8601DateFormat.mask) != 0) {
            context.setDateFormat("iso8601");
        } else {
            context.setDateFormat("millis");
        }

        if ((featuresValue & SerializerFeature.WriteMapNullValue.mask) != 0) {
            context.config(JSONWriter.Feature.WriteMapNullValue);
        }

        if ((featuresValue & SerializerFeature.WriteNullListAsEmpty.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNullListAsEmpty);
        }

        if ((featuresValue & SerializerFeature.WriteNullStringAsEmpty.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNullStringAsEmpty);
        }

        if ((featuresValue & SerializerFeature.WriteNullNumberAsZero.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNullNumberAsZero);
        }

        if ((featuresValue & SerializerFeature.WriteNullBooleanAsFalse.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNullBooleanAsFalse);
        }

        if ((featuresValue & SerializerFeature.BrowserCompatible.mask) != 0) {
            context.config(JSONWriter.Feature.BrowserCompatible);
            context.config(JSONWriter.Feature.EscapeNoneAscii);
        }

        if ((featuresValue & SerializerFeature.BrowserSecure.mask) != 0) {
            context.config(JSONWriter.Feature.BrowserSecure);
        }

        if ((featuresValue & SerializerFeature.WriteClassName.mask) != 0) {
            context.config(JSONWriter.Feature.WriteClassName);
        }

        if ((featuresValue & SerializerFeature.WriteNonStringValueAsString.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNonStringValueAsString);
        }

        if ((featuresValue & SerializerFeature.WriteEnumUsingToString.mask) != 0) {
            context.config(JSONWriter.Feature.WriteEnumUsingToString);
        }

        if ((featuresValue & SerializerFeature.WriteEnumUsingName.mask) != 0) {
            context.config(JSONWriter.Feature.WriteEnumsUsingName);
        }

        if ((featuresValue & SerializerFeature.NotWriteRootClassName.mask) != 0) {
            context.config(JSONWriter.Feature.NotWriteRootClassName);
        }

        if ((featuresValue & SerializerFeature.IgnoreErrorGetter.mask) != 0) {
            context.config(JSONWriter.Feature.IgnoreErrorGetter);
        }

        if ((featuresValue & SerializerFeature.WriteDateUseDateFormat.mask) != 0) {
            context.setDateFormat(JSON.DEFFAULT_DATE_FORMAT);
        }

        if ((featuresValue & SerializerFeature.BeanToArray.mask) != 0) {
            context.config(JSONWriter.Feature.BeanToArray);
        }

        if ((featuresValue & SerializerFeature.UseSingleQuotes.mask) != 0) {
            context.config(JSONWriter.Feature.UseSingleQuotes);
        }

        if ((featuresValue & SerializerFeature.MapSortField.mask) != 0) {
            context.config(JSONWriter.Feature.MapSortField);
        }

        if ((featuresValue & SerializerFeature.PrettyFormat.mask) != 0) {
            context.config(JSONWriter.Feature.PrettyFormat);
        }

        if ((featuresValue & SerializerFeature.WriteNonStringKeyAsString.mask) != 0) {
            context.config(JSONWriter.Feature.WriteNonStringKeyAsString);
        }

        if ((featuresValue & SerializerFeature.IgnoreNonFieldGetter.mask) != 0) {
            context.config(JSONWriter.Feature.IgnoreNonFieldGetter);
        }

        if ((featuresValue & SerializerFeature.NotWriteDefaultValue.mask) != 0) {
            context.config(JSONWriter.Feature.NotWriteDefaultValue);
        }

        if ((featuresValue & SerializerFeature.WriteBigDecimalAsPlain.mask) != 0) {
            context.config(JSONWriter.Feature.WriteBigDecimalAsPlain);
        }

        if ((featuresValue & SerializerFeature.QuoteFieldNames.mask) == 0
                && (featuresValue & SerializerFeature.UseSingleQuotes.mask) == 0
        ) {
            context.config(JSONWriter.Feature.UnquoteFieldName);
        }

        if (defaultTimeZone != null && defaultTimeZone != DEFAULT_TIME_ZONE) {
            context.setZoneId(defaultTimeZone.toZoneId());
        }

        context.config(JSONWriter.Feature.WriteByteArrayAsBase64);
        context.config(JSONWriter.Feature.WriteThrowableClassName);

        return context;
    }

从源码分析我们可以知道,JSON默认是换成""的

解决方法:

  SerializerFeature[] features = {
                SerializerFeature.MapSortField,
                SerializerFeature.WriteMapNullValue
        };

String sortedJson = JSON.toJSONString(JSON.parseObject(demo), features);

在使用时,也可以根据自己的需求来添加其他枚举类型,直接在后边添加即可。

最后,希望可以帮助到有需要的码友。

相关文章:

  • C++-AVL树
  • 云创智城充电系统:基于 SpringCloud 的高可用、可扩展架构详解-多租户、多协议兼容、分账与互联互通功能实现
  • 【第3章:卷积神经网络(CNN)——3.5 CIFAR-10图像分类】
  • idea插件开发,如何获取idea设置的系统语言
  • 电脑变慢、游戏卡顿,你的SSD固态可能快坏了!
  • 2024 CyberHost 语音+图像-视频
  • nodejs安装以及安装nvm控制nodejs版本教程
  • 30天开发操作系统 第 20 天 -- API
  • ESXi安装【真机和虚拟机】(超详细)
  • Docker 的安装与环境配置
  • 在nodejs中使用RabbitMQ(六)sharding消息分片
  • Pandas数据填充(fill)中的那些坑:避免机器学习中的数据泄露
  • Arduino 第四章:数字输出 —— 深入解析引脚差异与 LED 顺序点亮实践
  • 人生的转折点反而迷失了方向
  • 分布式技术
  • 【C++】C++-教师信息管理系统(含源码+数据文件)【独一无二】
  • LabVIEW用户界面设计原则
  • 【Elasticsearch】文本分析Text analysis概述
  • 面向 Data+AI 的新一代智能数仓平台
  • 实现Tree 树形控件的鼠标拖拽功能
  • 国有六大行一季度合计净赚超3444亿,不良贷款余额均上升
  • 卡尼领导的加拿大自由党在联邦众议院选举中获胜
  • 买新房可申领学位,广州南沙出台购房入学政策
  • 艺术与医学的对话,瑞金医院办了一个展览
  • 网络游戏用户规模和市场销售创新高,知识产权保护面临哪些挑战?
  • 俄罗斯称已收复库尔斯克州