///|
/// 两个 `Json` 值的深合并,对应 axios `utils.merge` 对普通对象的递归合并:
/// - 两边都是对象 → 逐键递归合并,只在请求级出现的键补进来;
/// - 其余组合 → 请求级整体覆盖。
///
/// 「数组整体替换而不是拼接」是刻意的:axios 的 `utils.merge` 只对 plain object
/// 递归,数组走 `val.slice()` 直接替换。所以默认值里 `tags: ["a"]`、
/// 请求里 `tags: ["b"]` 的结果是 `["b"]`,而不是 `["a", "b"]`。
pub fn merge_json(base : Json, request : Json) -> Json {
match (base, request) {
(Object(base_fields), Object(request_fields)) => {
// copy 后再写:base 可能属于另一个 Config,就地改会让原配置跟着变。
// Json 是只读类型,只能经由 Json::object 重新构造。
let merged = base_fields.copy()
for key, value in request_fields {
let next = match merged.get(key) {
Some(existing) => merge_json(existing, value)
None => value
}
merged[key] = next
}
Json::object(merged)
}
_ => request
}
}
///|
/// `Json?` 层面的深合并:两侧都可能没有值,`None` 表示未提供。
///
/// 与 `merge_headers` 同构,唯一区别是合并函数换成了 `merge_json`。
/// 用于 `params` 这类以 JSON 对象承载的配置项。
pub fn merge_json_option(base : Json?, request : Json?) -> Json? {
match (base, request) {
(None, None) => None
(Some(base), None) => Some(base)
(None, Some(request)) => Some(request)
(Some(base), Some(request)) => Some(merge_json(base, request))
}
}