You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

org.json.JSONObject实例化时自动移除BigDecimal末尾零的问题

如何避免JSONObject解析时移除数值末尾的零?

这个问题的核心原因在于org.json库的JSONObject会自动将JSON中的数值类型解析为Java的Number子类(比如Double或Integer),而这些类型在toString时会自动去掉末尾无意义的零——比如473935.00会被解析为Double类型的473935.0,最终输出时就变成了473935;585538.30会被解析为585538.3,输出时末尾的零就消失了。

下面给你几种可行的解决方案,根据你的需求选择:


方案1:将数值以字符串形式存储(推荐,适合需要严格保留格式的场景)

如果你的业务需要严格保留小数位数(比如金额场景),最稳妥的方式是让API返回时就把这些数值以字符串类型返回,比如:

{ 
  "id": "4d27afb18bfa4eb5917beee9aaddfa76", 
  "hedgeId": 205598, 
  "sellCurrency": "USD", 
  "buyCurrency": "EUR", 
  "buyAmount": "473935.00", 
  "sellAmount": "585538.30" 
}

这样JSONObject解析后,buyAmount和sellAmount会被保留为字符串类型,末尾的零自然不会丢失。

如果API无法修改返回格式,你可以在解析前手动将数值替换为字符串(用正则表达式),但这种方式要注意边界情况,比如避免误改其他数值:

// 简单的正则替换,将带两位小数的数值转换为字符串
String modifiedJson = thatStringAbove.replaceAll("(\\d+\\.\\d{2})", "\"$1\"");
JSONObject foo = new JSONObject(modifiedJson);
// 此时foo中的buyAmount和sellAmount是字符串,保留了末尾零

方案2:使用更灵活的JSON库(比如Gson或Jackson)自定义序列化规则

org.json库的灵活性较差,如果你能切换到Gson或Jackson,可以通过自定义序列化逻辑强制保留小数位数。

用Gson实现:

  1. 定义一个自定义序列化器,指定保留两位小数:
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.text.DecimalFormat;

public class FixedDecimalSerializer implements JsonSerializer<BigDecimal> {
    private final DecimalFormat decimalFormat;

    public FixedDecimalSerializer() {
        decimalFormat = new DecimalFormat("#.00");
        decimalFormat.setMinimumFractionDigits(2); // 强制保留两位小数
        decimalFormat.setMaximumFractionDigits(2);
        decimalFormat.setGroupingUsed(false); // 不使用千分位分隔符
    }

    @Override
    public JsonElement serialize(BigDecimal value, Type type, JsonSerializationContext context) {
        return new JsonPrimitive(decimalFormat.format(value));
    }
}
  1. 初始化Gson并使用该序列化器:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.math.BigDecimal;

// 假设你有对应的实体类HedgeTransaction,字段类型用BigDecimal
HedgeTransaction transaction = new Gson().fromJson(thatStringAbove, HedgeTransaction.class);

Gson gsonWithFixedDecimals = new GsonBuilder()
        .registerTypeAdapter(BigDecimal.class, new FixedDecimalSerializer())
        .create();

String formattedJson = gsonWithFixedDecimals.toJson(transaction);
// formattedJson中的buyAmount会是"473935.00",sellAmount是"585538.30"

用Jackson实现:

  1. 自定义序列化器并注册到ObjectMapper:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;

public class FixedDecimalJacksonSerializer extends JsonSerializer<BigDecimal> {
    private final DecimalFormat decimalFormat = new DecimalFormat("#.00");

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString(decimalFormat.format(value));
    }
}

// 初始化ObjectMapper
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(BigDecimal.class, new FixedDecimalJacksonSerializer());
mapper.registerModule(module);

// 解析并序列化
HedgeTransaction transaction = mapper.readValue(thatStringAbove, HedgeTransaction.class);
String formattedJson = mapper.writeValueAsString(transaction);

方案3:在org.json的JSONObject中手动格式化数值

如果必须使用org.json库,可以在解析后手动将数值格式化为带两位小数的字符串,再放回JSONObject:

import org.json.JSONObject;
import java.math.BigDecimal;
import java.text.DecimalFormat;

JSONObject foo = new JSONObject(thatStringAbove);
DecimalFormat df = new DecimalFormat("#.00");

// 处理buyAmount
BigDecimal buyAmount = foo.getBigDecimal("buyAmount");
foo.put("buyAmount", df.format(buyAmount));

// 处理sellAmount
BigDecimal sellAmount = foo.getBigDecimal("sellAmount");
foo.put("sellAmount", df.format(sellAmount));

// 此时foo.toString()会保留末尾的零

这种方式需要逐个处理需要保留格式的字段,适合字段数量较少的场景。


内容的提问来源于stack exchange,提问作者iamkenos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:36:07