阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。
把所有金额字段写成
minimum: 0
,表面上很严谨,却会把正常的退款记录挡在门外。金额有没有提取成数字,与这笔业务允不允许负数,是两个问题。应该先确认单据的含义,再写范围规则。
先定义负号代表什么
本文合成协议约定:普通收费非负,退款以负金额表示。真实系统也可能使用“正金额加退款类型”的记账方式。两种方式都能成立,但不能在同一个接口里靠读者猜。这里的零点边界是示例协议,不是财务行业的统一标准。
让类型决定约束
JSON Schema 的
minimum
包含边界,
exclusiveMinimum
不包含边界。若业务要求严格为正,不能用
minimum: 0
。先列出允许零值的场景,再选关键字,避免把免费项目、冲销或预估值误判为错误。
from jsonschema import Draft202012Validator
schema = {
"type": "object", "required": ["kind", "amount"],
"additionalProperties": False,
"properties": {"kind": {"enum": ["charge", "refund"]},
"amount": {"type": "number"}},
"allOf": [
{"if": {"properties": {"kind": {"const": "charge"}}},
"then": {"properties": {"amount": {"minimum": 0}}}},
{"if": {"properties": {"kind": {"const": "refund"}}},
"then": {"properties": {"amount": {"exclusiveMaximum": 0}}}}
]
}
v = Draft202012Validator(schema)
valid = lambda x: not list(v.iter_errors(x))
assert valid({"kind": "charge", "amount": 0})
assert valid({"kind": "refund", "amount": -12.5})
assert not valid({"kind": "refund", "amount": 12.5})
assert not valid({"kind": "charge", "amount": True})
assert not valid({"amount": 12.5})
示例依赖
jsonschema
,按 Draft 2020-12 校验。它没有做币种换算,也没有验证分项与合计关系。货币计算需要明确精度和舍入策略,不能因为数值通过 Schema 就改用浮点数随意累加。
报错需要指出业务上下文
观察
这里的处理
还需核对
退款为正数
拒绝
是符号丢失还是来源采用另一协议
收费为零
接受结构
是否属于免费项目
金额为字符串
拒绝类型
千位符、币种与小数规则
类型缺失
拒绝
不按金额符号猜单据类型
别用自动取绝对值掩盖错误
OCR 漏掉短横线、翻译移动负号和业务采用相反符号约定,可能表现为同一个异常。直接调用
abs()
会消除最重要的诊断线索。应保存原文片段、页号和解析前字符串,再决定重提取还是人工复核。
交付时一起检查金额与类型
用
OmniDoc(产品入口)
处理含金额的文档时,可以把这张规则表作为译后验收的一部分:不只看数字有没有丢,还要看退款、贷项等语境有没有改变。工具帮助完成翻译,金额协议仍应由业务方明确。
参考:
JSON Schema 数值约束
。
- 1 -
更新于 2026-10-08