You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 5游戏对话JSON文件创建与解析技术咨询

游戏对话JSON结构修正与Swift解析方案

一、当前JSON结构的问题及调整方案

你的JSON存在几个影响解析的问题,调整后才能和Swift代码正确匹配:

  1. 拼写错误:所有diagloue键名需修正为dialogue(少写了字母a)
  2. Speaker枚举值不匹配:
    • 你的Speaker枚举rawValue是驼峰格式(如CharacterA),但JSON里写的是"Character A"(带空格)、"protagonist"(全小写),需统一格式。建议JSON使用和枚举一致的驼峰/大小写:
      • "CharacterA"代替"Character A"
      • "Protagonist"代替"protagonist"
  3. 冗余字段:外层chapter数组中每个对象的speaker字段冗余,对话列表已包含每个发言的角色,可直接删除简化结构。

调整后的JSON示例:

{
  "chapter": [
    {
      "conversation": [
        {
          "speaker": "CharacterA",
          "dialogue": "Hello stranger, what brought you here?"
        },
        {
          "speaker": "Protagonist",
          "dialogue": "I'm here to look for some guy."
        },
        {
          "speaker": "CharacterA",
          "dialogue": "I've lived here all my life. Maybe I can help you."
        }
      ]
    },
    {
      "conversation": [
        {
          "speaker": "Protagonist",
          "dialogue": "Why is the gate closed?"
        },
        {
          "speaker": "CharacterB",
          "dialogue": "No one is allowed to leave town until further notice."
        }
      ]
    }
  ]
}

若需保留章节对应主要角色,可将外层speaker改为mainSpeaker,避免和对话内speaker混淆,同时调整Swift结构体对应。

二、Swift 5解析代码修正

你的解析代码需和自定义Speaker枚举、Dialogue结构体对齐,同时处理安全解包和枚举解码:

1. 统一数据模型

保留原有Speaker枚举,调整解析用结构体以匹配自定义Dialogue:

enum Speaker: String, Decodable {
    case Protagonist
    case CharacterA
    case CharacterB
    case CharacterC
}

// 原自定义Dialogue结构体,适配解析需求
struct Dialogue {
    var speaker: Speaker
    var messages: [String]
    
    // 从JSON单条对话初始化
    init(speaker: Speaker, message: String) {
        self.speaker = speaker
        self.messages = [message]
    }
}

// 对应JSON的对话组结构
struct ConversationGroup: Decodable {
    let conversation: [SingleDialogue]
    
    // 解析JSON单条对话的临时结构体
    struct SingleDialogue: Decodable {
        let speaker: Speaker
        let dialogue: String
    }
    
    // 转换为自定义Dialogue数组(支持按角色合并消息)
    func toDialogues() -> [Dialogue] {
        // 按角色分组消息
        let grouped = Dictionary(grouping: conversation) { $0.speaker }
        return grouped.map { Dialogue(speaker: $0.key, message: $0.value.map { $0.dialogue }.joined(separator: "\n")) }
        // 若不需要合并,直接转换:
        // return conversation.map { Dialogue(speaker: $0.speaker, message: $0.dialogue) }
    }
}

// 对应JSON根结构
struct ChapterData: Decodable {
    let chapter: [ConversationGroup]
}

2. 安全的JSON加载与解析

避免强制解包,使用可选绑定和错误处理:

func loadDialogues() throws -> [Dialogue] {
    guard let path = Bundle.main.path(forResource: "conversation", ofType: "json"),
          let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
        throw NSError(domain: "DialogueError", code: 0, userInfo: [NSLocalizedDescriptionKey: "无法加载对话文件"])
    }
    
    let decoder = JSONDecoder()
    // 若JSON枚举值和Swift枚举大小写不一致,可开启大小写不敏感解码:
    // decoder.keyDecodingStrategy = .convertFromSnakeCase
    
    let chapterData = try decoder.decode(ChapterData.self, from: data)
    // 合并所有章节的对话
    return chapterData.chapter.flatMap { $0.toDialogues() }
}

// 使用示例
do {
    let dialogues = try loadDialogues()
    for dialogue in dialogues {
        print("\(dialogue.speaker.rawValue): \(dialogue.messages.joined())")
    }
} catch {
    print("解析错误:\(error.localizedDescription)")
}

关键说明:

  • 新增SingleDialogue临时结构体直接解析JSON单条对话,再转换为自定义Dialogue(支持按角色合并多条消息)
  • 让Speaker枚举遵循Decodable协议,直接支持JSON解码
  • 用可选绑定替代强制解包,避免崩溃
  • 加入错误处理,便于排查加载/解析问题

内容的提问来源于stack exchange,提问作者Bob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:23:14