将 JSON 文件解码为不同的目标数组

Posted

技术标签:

【中文标题】将 JSON 文件解码为不同的目标数组【英文标题】:Decoding a JSON file into different target arrays 【发布时间】:2020-01-28 23:04:18 【问题描述】:

我的代码可以解码如下所示的 JSON 文件:

[
  
    "id" : "WIW-919",
    "factionGroupName" : "CommonWealth",
    "characters" : [
      
        "id" : "NPJ-160",
        "name" : "Agatha Tavernfrau",
        "faction" : "CommonWealth",
        "mugShot" : "AgathaMugShot",
        "standeeImage" : "AgathaStandee",
        "cardBackImage" : "AgathaSignaturev1",
        "cardFrontImage" : "AgathaFrontv1",
        "keywords" : [
          "Human"
        ]
      ,  
  
    "id" : "PAQ-610",
    "factionGroupName" : "Dominion",
    "characters" : [
      
        "id" : "JKA-020",
        "name" : "Doug the flatulent",
        "faction" : "Dominion",
        "mugShot" : "DougMugShot",
        "standeeImage" : "DougStandee",
        "cardBackImage" : "DougSignaturev2",
        "cardFrontImage" : "DougFrontv2",
        "keywords" : [
          "Animal",
          "Goblin"
        ]
      
    ]
  
]

本质上,我有两个使用 factionGroupName 的***结构,然后它们又使用另一个结构来解码字符对象。

我能够读入完整的 JSON 文件,然后 foreach 循环遍历内容并将它们输出到列表等中。

但是 - 我真正想做的是解码 JSON 文件并将***数组放入两个不同的结构中 - 所以如果 factionGroupName 等于 CommonWealth,则使用名为 commonwealth 的结构,但如果 factionGroupName 等于 Dominion 则使用不同的结构。

我可以这样做吗?还是我需要使用不同的 JSON 文件?

我正在努力阅读如何使用自定义解码器规则,但我想我只想对 factionGroupName 变量进行值测试并更改它然后调用的结构?


这是当前要在 Json 中读取的代码:

import SwiftUI
struct markTestName: Codable, Identifiable 
    var id: String
    var factionGroupName: String
    var characters: [charDetail]

struct charDetail: Codable, Equatable, Identifiable
    var id: String
    var name: String
    var faction: String
    var mugShot : String
    var standeeImage : String
    var cardBackImage : String
    var cardFrontImage : String
    var keywords: [String]

【问题讨论】:

我的问题是:你们以后会不会有更多的派系?使用您尝试采用的方法,如果您为每个组创建一个变量,可扩展性将具有挑战性。为什么不想办法利用比较来使代码更通用。 可能会有更多派系,但可能只有 3 或 4 个。 characters数组的属性有区别吗?似乎没有。从 JSON 中加载数据然后简单地将其拆分为不同的数组或按派系键入的字典或类似的东西不是更容易吗? 我仍然希望能够读取 JSON 数据并说单击一个英联邦按钮,然后仅显示与英联邦相关联的字符列表 - 或者有一个完整列表和如果项目未对齐等,则隐藏项目的选项等。 这听起来绝对像 [String:[Character]] 的字典是你想要的。 【参考方案1】:

我将首先创建几个 Codable 结构来保存您的 JSON 数据:

struct Faction: Codable 
    let id: String
    let name: String
    let characters: [Character]


struct Character: Codable 
    let id: String
    let name: String
    let faction: String
    let mugShot: String
    let standeeImage: String
    let cardBackImage: String
    let cardFrontImage: String
    let keywords: [String]

然后创建一个结构来保存您的派系(以及您可能需要的任何其他数据)

struct GameData 
    let factions:[Faction]

    var factionNames:[String] 
        get 
            return Array(Set(factions.compactMap( $0.name )))
        
    

    func faction(named: String) -> Faction? 
        return factions.first  (faction) -> Bool in
            faction.name == named
        
         

如果 factions 是您从 JSON 获得的 [Faction] 数组,您将使用以下方法创建 GameData 的实例

let gameData = GameData(factions: factions)

现在,您可以使用以下方法获得特定派系:

if let commonwealth = gameData.faction(named:"Commonwealth") 
   // Do something
 else 
   // Faction not found

由于您的派系数量相对较少,因此仅使用first(where:) 搜索数组并不是一个大的性能问题,尤其是您可能只执行一次并将派系保存在另一个变量中。

您还可以使用gameData.factionNames获取所有派系的列表(以动态创建您的派系过滤按钮等元素)

【讨论】:

我将尝试并遵循这一切的目标。我将如何使用该 gameData.factionNames 生成一个列表?甚至查看内容?谢谢。 嗯,gameData.factionNames 是一个字符串数组;您可以对其进行迭代,为数组中的每个元素调用faction(named:),然后为每个派系循环遍历characters 数组。您还可以使用数组为 tableview 提供数据。 请假设我很傻。我不知道任何基本的 Swift (我知道我应该在这里发帖之前学习!!) - 我可以使用普通的 foreach(gameData.factionNames? 是的...这取决于您希望如何显示数据。无论您使用的是 SwiftUI 列表还是 UIKit 表格视图... 使用 SwiftUI - 只想将数组中的派系名称输出到列表中以显示在屏幕上 - 所以我可以看到内容是正确的 - 即在我的 json 数据中包含派系:)

以上是关于将 JSON 文件解码为不同的目标数组的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JSON 解码为不同的类型?

Elm:将具有单个元素的 JSON 数组解码为字符串

JSON 可解码嵌套数组具有不同的格式和类型

如何将json数据解码为objective-c中的数组[重复]

无法将 JSON 解码为 PHP 数组并显示在 HTML 表中

为啥我不能在 Swift 中解码我的 JSON 文件?