fix: tolerate null legacy custom-world profile

This commit is contained in:
kdletters
2026-05-21 17:49:07 +08:00
parent 41075e41a2
commit 224a26d318
3 changed files with 60 additions and 1 deletions

View File

@@ -694,7 +694,13 @@ fn parse_optional_json_object(
error: CustomWorldFieldError,
) -> Result<Map<String, Value>, CustomWorldFieldError> {
match normalize_optional_json_slice(value) {
Some(value) => parse_required_json_object(&value, error),
Some(value) => match serde_json::from_str::<Value>(&value) {
Ok(Value::Object(object)) => Ok(object),
// 中文注释:跨层可选字段经 serde 结构体序列化后可能显式落成 null
// 对 optional JSON object 而言 null 等价于未提供,不能阻断发布链路。
Ok(Value::Null) => Ok(Map::new()),
_ => Err(error),
},
None => Ok(Map::new()),
}
}
@@ -1018,6 +1024,49 @@ mod tests {
use super::*;
use serde_json::json;
fn build_test_compile_input(
legacy_result_profile_json: Option<String>,
) -> CustomWorldPublishedProfileCompileInput {
CustomWorldPublishedProfileCompileInput {
session_id: "session-1".to_string(),
profile_id: "cwprof_001".to_string(),
owner_user_id: "user-1".to_string(),
draft_profile_json: json!({
"name": "潮雾列岛",
"summary": "群岛与旧灯塔之间的沉船疑案。",
"playableNpcs": [],
"storyNpcs": [],
"landmarks": []
})
.to_string(),
legacy_result_profile_json,
setting_text: "海图会在午夜改写群岛航路。".to_string(),
author_display_name: "创作者".to_string(),
updated_at_micros: 1,
}
}
#[test]
fn published_profile_compile_treats_null_legacy_result_profile_as_absent() {
let snapshot = build_custom_world_published_profile_compile_snapshot(
build_test_compile_input(Some("null".to_string())),
)
.expect("null legacy result profile should be treated as absent");
assert_eq!(snapshot.profile_id, "cwprof_001");
assert_eq!(snapshot.world_name, "潮雾列岛");
}
#[test]
fn published_profile_compile_rejects_non_object_legacy_result_profile() {
let error = build_custom_world_published_profile_compile_snapshot(
build_test_compile_input(Some("[]".to_string())),
)
.expect_err("array legacy result profile should still be invalid");
assert_eq!(error, CustomWorldFieldError::InvalidLegacyResultProfileJson);
}
#[test]
fn publish_setting_text_falls_back_to_draft_profile_when_seed_is_empty() {
let payload = Map::new();