# PR #28094 完整报告

- 仓库：`sgl-project/sglang`
- 标题：fix(server): serialize nested dict config values as JSON
- 合并时间：2026-06-13 10:27
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/28094

---

# 执行摘要

- 一句话：修复嵌套字典配置项 JSON 序列化问题
- 推荐动作：建议合并。该修复简洁且必要，专门针对已报告的启动失败问题，并包含回归测试。

# 功能与动机

PR body 指出：`--config` 目前对嵌套 YAML dict 值使用 `str(value)`，对于声明为 `type=json.loads` 的参数，会产生 Python repr 字符串，如 `{'temperature': 0.5, 'top_p': 0.9}`，导致 `json.loads` 在 argparse 校验阶段拒绝，服务启动前退出。影响 `--mm-process-config`、`--preferred-sampling-params`、`--limit-mm-data-per-request` 等字典类型配置参数。此问题在 #14085 修复了布尔值后仍存在。

# 实现拆解

1. **修改配置转换逻辑**：在 `_convert_config_to_args` 方法中，对 `value` 为 `dict` 类型增加专属 `elif` 分支，调用 `json.dumps(value)` 序列化后通过 `_add_scalar_arg` 传入参数列表。
2. **添加导入**：在 `server_args_config_parser.py` 顶部添加 `import json`。
3. **新增回归测试**：在 `test_server_args.py` 的 `TestPrepareServerArgs` 类中添加 `test_config_nested_dict_args_are_json` 测试方法，使用临时 YAML 文件模拟 `--mm-process-config` 配置，验证 `ConfigArgumentMerger` 正确将字典序列化为 JSON 字符串，且 `parser.parse_args` 后能正确解析。
4. **测试导入调整**：在测试文件中导入 `ConfigArgumentMerger`。

关键文件：
- `python/sglang/srt/server_args_config_parser.py`（模块 配置解析；类别 source；类型 core-logic；符号 _convert_config_to_args）: 核心修复文件：在 `_convert_config_to_args` 方法中增加 `elif isinstance(value, dict)` 分支，使用 `json.dumps` 序列化字典值。
- `test/registered/unit/server_args/test_server_args.py`（模块 服务参数；类别 test；类型 test-coverage；符号 test_config_nested_dict_args_are_json）: 回归测试文件：新增 `test_config_nested_dict_args_are_json` 测试方法，验证嵌套字典配置在转换后能被正确解析为 JSON 对象。

关键符号：_convert_config_to_args, test_config_nested_dict_args_are_json

## 关键源码片段

### `python/sglang/srt/server_args_config_parser.py`

核心修复文件：在 `_convert_config_to_args` 方法中增加 `elif isinstance(value, dict)` 分支，使用 `json.dumps` 序列化字典值。

```python
# python/sglang/srt/server_args_config_parser.py
import json  # 新增导入

def _convert_config_to_args(self, config: Dict[str, Any]) -> List[str]:
    """Convert configuration dictionary to argument list."""
    args = []
    for key, value in config.items():
        key_norm = key.replace("-", "_")
        if key_norm in self.unsupported_actions:
            action = self.unsupported_actions[key_norm]
            msg = f"Unsupported config option '{key_norm}' with action '{action.__class__.__name__}'"
            raise ValueError(msg)
        if isinstance(value, bool):
            self._add_boolean_arg(args, key, value)
        elif isinstance(value, list):
            self._add_list_arg(args, key, value)
        elif isinstance(value, dict):
            # 修复：使用 json.dumps 序列化字典，避免 str() 产生 Python repr 字符串
            self._add_scalar_arg(args, key, json.dumps(value))
        else:
            self._add_scalar_arg(args, key, value)
    return args

```

### `test/registered/unit/server_args/test_server_args.py`

回归测试文件：新增 `test_config_nested_dict_args_are_json` 测试方法，验证嵌套字典配置在转换后能被正确解析为 JSON 对象。

```python
# test/registered/unit/server_args/test_server_args.py
from sglang.srt.server_args_config_parser import ConfigArgumentMerger  # 新增导入

def test_config_nested_dict_args_are_json(self):
    with tempfile.NamedTemporaryFile(mode="w", suffix=".yaml", delete=False) as f:
        # 模拟 YAML 配置：mm-process-config 是嵌套字典
        f.write("mm-process-config:\n  image:\n    resize: 128\n")
        config_file = f.name
    try:
        parser = server_args_module.argparse.ArgumentParser()
        ServerArgs.add_cli_args(parser)
        merged = ConfigArgumentMerger(parser).merge_config_with_args(
            ["--config", config_file, "--model-path", DEFAULT_SMALL_MODEL_NAME_FOR_TEST_QWEN]
        )
        # 获取转换后的参数值
        value = merged[merged.index("--mm-process-config") + 1]
        parsed = parser.parse_args(merged)
        # 验证 value 是有效的 JSON 字符串，且解析后与原始字典一致
        self.assertEqual(json.loads(value), {"image": {"resize": 128}})
        self.assertEqual(parsed.mm_process_config, {"image": {"resize": 128}})
    finally:
        os.unlink(config_file)

```

# 评论区精华

无 review 讨论。PR 无任何 review 评论。

- 暂无高价值评论线程

# 风险与影响

- 风险：风险极低：变更仅增加了一个 `elif isinstance(value, dict)` 分支，并引入了 `json.dumps` 调用，路径与现有 `_add_scalar_arg` 一致。测试覆盖了典型的嵌套字典场景（`mm-process-config`），未影响布尔值或列表路径。但需注意：若配置值为 dict 但其中含有非 JSON 可序列化类型（如 `set`），`json.dumps` 可能抛出异常，不过 YAML 配置中此类情况罕见。
- 影响：直接影响所有使用 `--config` 且包含字典类型参数的用户，使其能正常启动服务。受影响参数包括 `--mm-process-config`、`--preferred-sampling-params`、`--limit-mm-data-per-request`、`--extra-metric-labels` 等。对其他配置参数无影响。
- 风险标记：暂无

# 关联脉络

- PR #14085 Fix parse args from file(#13911): 关联 PR#14085 修复了布尔值配置的类似问题，本 PR 是同一 config 解析路径中针对字典类型的补全修复。