如何控制Python中json.dump的科学计数法格式?
控制json.dump科学计数法格式化方式的解决方案
可以通过自定义JSONEncoder来统一科学计数法的输出格式,解决不同平台下json.dump输出1e-6和1e-06的差异问题。
方法:自定义浮点数字符串编码器
继承标准库的json.JSONEncoder,重写default方法来控制浮点数的格式化逻辑,确保所有机器输出一致的格式。
示例1:统一输出不带前导零的格式(如1e-6)
import json class CompactSciNotationEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, float): # 先以科学计数法格式化浮点数,保留足够精度 sci_str = "{:.10e}".format(obj) # 替换"e-0"/"e+0"为"e-"/"e+",移除指数部分的前导零 sci_str = sci_str.replace("e-0", "e-").replace("e+0", "e+") # 移除末尾多余的零和小数点(如"1.23000e-6"→"1.23e-6") if "." in sci_str: sci_str = sci_str.rstrip('0').rstrip('.') return sci_str # 其他类型使用默认序列化逻辑 return super().default(obj) # 使用示例 sample_data = {"small_num": 0.000001, "another_num": 0.0000123} print(json.dumps(sample_data, cls=CompactSciNotationEncoder)) # 输出:{"small_num": "1e-6", "another_num": "1.23e-5"}
示例2:统一输出带前导零的格式(如1e-06)
import json class PaddedSciNotationEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, float): sci_str = "{:.10e}".format(obj) # 拆分数字部分和指数部分,确保指数为两位 num_part, exp_part = sci_str.split('e') exp_sign = exp_part[0] exp_digits = exp_part[1:].zfill(2) sci_str = f"{num_part}e{exp_sign}{exp_digits}" # 清理末尾多余的零和小数点 if "." in sci_str: sci_str = sci_str.rstrip('0').rstrip('.') return sci_str return super().default(obj) # 使用示例 sample_data = {"small_num": 0.000001, "another_num": 0.0000123} print(json.dumps(sample_data, cls=PaddedSciNotationEncoder)) # 输出:{"small_num": "1e-06", "another_num": "1.23e-05"}
注意事项
- 上述示例会将浮点数序列化为字符串类型,但JSON解析器(包括Python的
json.loads)可以正常将这些字符串解析为数值类型。 - 如果需要保持JSON中的数值类型而非字符串,可以修改编码器逻辑,将格式化后的字符串转回
float,但需注意部分Python版本可能仍会按默认规则重新格式化,因此字符串格式的方案更稳定。
内容的提问来源于stack exchange,提问作者mitchute
相关产品推荐
相关产品推荐

