# 配置字段解析：标量 vs 数组

适用于工作台后端读取 `数据/*.json` 配置做分支/成员判断的任何地方（政策、促销、权限覆盖、限流覆盖）。

## 一、本类 bug 长什么样（静默跳过）

**症状**：某个业务线分支永远读不到本应命中的配置，另一个分支正常，**全程无报错、无日志**。

**实例**：诊断原料（da）分支读不到 `数据/sales_policy.json` 里 `line` 为 `both` 的政策（促销期外 700 元费用额度等），生命科学（ls）分支正常。

**根因**：

```python
# ❌ 错：p.get('line') 的值是字符串 'both'（不是数组）
#         'da' not in 'both' 恒真 → 每条政策都被 continue 跳过
if line not in (p.get('lines') or p.get('line') or [line, 'both']):
    continue
```

字符串是序列，`in` 对字符串做的是**子串**判断，`'da' in 'both'` 为假——于是整类记录被静默排除。

## 二、正确写法：先归一成列表

```python
ln = p.get('lines') or ([p['line']] if p.get('line') else [])
if 'both' not in ln and line not in ln:
    continue
```

这里**同时**兼容四种数据形态，因为同一份配置里都出现过：

| 字段形态 | 含义 | 处理 |
|---|---|---|
| `"line": "both"` | 标量，适用全部业务线 | 包成 `['both']` |
| `"line": "da"` | 标量，单线 | 包成 `['da']` |
| `"lines": ["da","ls"]` | 数组 | 直接用 |
| 两字段都缺 | 默认适用全部 | 空列表 + `'both'` 豁免分支 |

## 三、铁律

1. **读配置做成员判断前，先确认字段是标量还是数组。** 同一字段在不同记录里两种形态都可能出现；`in` 对两者的语义不同（子串 vs 成员），不会报错，只会静默给错结果。
2. **改完用一条“应该命中”的记录做断言验证。** 本例：断言 `line=da` 能读到那条 700 元政策。
3. **不要只看“不报错”。** 静默跳过是本类 bug 唯一的信号——它不进日志、不进异常，只能靠正向断言抓。
4. 同类信号：数据解析产出 **0 条**（如月度 xlsx 底座生成 0 条目 / 0 货号）也是静默失败，必须显式断言条数。

## 四、快速自检命令

```bash
# 看同一个字段在全库里有几种形态（标量/数组混用会同时出现）
/usr/bin/python3 -c "
import json, collections
d = json.load(open('数据/sales_policy.json', encoding='utf-8'))
c = collections.Counter(type(p.get('lines') or p.get('line')).__name__ for p in d.get('policies', []))
print(c)
"
```

输出里同时出现 `str` 和 `list` 就是本类 bug。
