与在SwiftUI中基于ID号解析JSON数据相关的问题。

huangapple go评论68阅读模式
英文:

Question related to parsing JSON Data based on ID number in SwiftUI

问题

以下是翻译好的内容:

I am new to SwiftUI and have encountered problems parsing data from JSON files in SwiftUI. At now, I can pass all the data in the JSON file but what I want is to parse a list of data based on their id number.

Here is my json file:
这是我的JSON文件:

As you can see from the JSON file, in my business segments section, I listed down a list of numbers. These numbers are the id number associated with the specific company in the company section. What I wish to do is have six buttons in the contentView. Each button represents one business segment. As I click on each button, it will jump to CompanyName View, where all the companies related to each business segment are shown. However, what I could do and what I have tired is to list all the companies in the CompanyName View.
正如您从JSON文件中所看到的,在我的业务段部分,我列出了一列数字。这些数字是与公司部分中的特定公司关联的ID号码。我希望在contentView中有六个按钮。每个按钮代表一个业务段。当我点击每个按钮时,它会跳转到CompanyName View,显示与每个业务段相关的所有公司。然而,我能够做的和我已经尝试过的是在CompanyName View中列出所有的公司。

Hence, I need some help. I will show you different files in my project.
因此,我需要一些帮助。我将向您展示我的项目中的不同文件。

CompanyViewModel.swift, where handle all the parsing from json:
CompanyViewModel.swift,用于处理所有来自JSON的解析:

ContentView.swift
ContentView.swift

CompanyName.swift
CompanyName.swift

英文:

I am new to SwiftUI and have encountered problems parsing data from JSON files in SwiftUI. At now, I can pass all the data in the JSON file but what I want is to parse a list of data based on their id number.

Here is my json file:

{
  "client": {
    "id": 200,
    "first_name": "Luke",
    "last_name": "",
    "email": "luke@abc.com"
  },
  "business_segments": [
    {
      "id": 1,
      "name": "Segment A",
      "status": "Open",
      "companies": [
        5,
        6,
        7
      ]
    },
    {
      "id": 2,
      "name": "Segment B",
      "status": "Open",
      "companies": [
        1,
        2,
        4
      ]
    },
    {
      "id": 3,
      "name": "Segment C",
      "status": "Open",
      "companies": [
        3,
        8,
        12
      ]
    },
    {
      "id": 4,
      "name": "Segment D",
      "status": "Open",
      "companies": [
        9,
        10,
        15
      ]
    },
    {
      "id": 5,
      "name": "Segment E",
      "status": "Open",
      "companies": [
        11,
        13,
        14,
        16
      ]
    },
    {
      "id": 6,
      "name": "Segment F",
      "status": "Open",
      "companies": [
        17,
        18
      ]
    }
  ],
  "companies": [
    {
      "id": 1,
      "name": "COMPANY A",
      "status": "Open"
    },
    {
      "id": 2,
      "name": "COMPANY B",
      "status": "Open"
    },
    {
      "id": 3,
      "name": "COMPANY C",
      "status": "Open"
    },
    {
      "id": 4,
      "name": "COMPANY D",
      "status": "Open"
    },
    {
      "id": 5,
      "name": "COMPANY E",
      "status": "Open"
    },
    {
      "id": 6,
      "name": "COMPANY F",
      "status": "Open"
    },
    {
      "id": 7,
      "name": "COMPANY G",
      "status": "Open"
    },
    {
      "id": 8,
      "name": "COMPANY H",
      "status": "Open"
    },
    {
      "id": 9,
      "name": "COMPANY I",
      "status": "Open"
    },
    {
      "id": 10,
      "name": "COMPANY J",
      "status": "Open"
    },
    {
      "id": 11,
      "name": "COMPANY K",
      "status": "Open"
    },
    {
      "id": 12,
      "name": "COMPANY L",
      "status": "Open"
    },
    {
      "id": 13,
      "name": "COMPANY M",
      "status": "Open"
    },
    {
      "id": 14,
      "name": "COMPANY N",
      "status": "Open"
    },
    {
      "id": 15,
      "name": "COMPANY O",
      "status": "Open"
    },
    {
      "id": 16,
      "name": "COMPANY P",
      "status": "Open"
    },
    {
      "id": 17,
      "name": "COMPANY Q",
      "status": "Open"
    },
    {
      "id": 18,
      "name": "COMPANY R",
      "status": "Open"
    }
  ]
}

As you can see from the JSON file, in my business segments section, I listed down a list of numbers. These numbers are the id number associated with the specific company in the company section. What I wish to do is have six buttons in the contentView. Each button represents one business segment. As I click on each button, it will jump to CompanyName View, where all the companies related to each business segment are shown. However, what I could do and what I have tired is to list all the companies in the CompanyName View.
Hence, I need some help. I will show you different files in my project.

CompanyViewModel.swift, where handle all the parsing from json:

import Foundation


 // MARK: - CompanyData
 struct CompanyData: Codable,Hashable {
     let client: Client
     let businessSegments, companies: [BusinessSegment]

     enum CodingKeys: String, CodingKey {
         case client
         case businessSegments = "business_segments"
         case companies
     }
 }

 // MARK: - BusinessSegment
 struct BusinessSegment: Codable,Hashable {
     let id: Int
     let name: String
     let status: Status
     let companies: [Int]?
 }

 enum Status: String, Codable {
     case statusOpen = "Open"
 }

 // MARK: - Client
 struct Client: Codable,Hashable {
     let id: Int
     let firstName, lastName, email: String

     enum CodingKeys: String, CodingKey {
         case id
         case firstName = "first_name"
         case lastName = "last_name"
         case email
     }
 }

 
 class CompanyViewModel:ObservableObject{
     
      @Published var company_data: [CompanyData] = []
     
     func getUserData(){
         
         guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
             print("Invalid URL")
             return
         }
         
         let task = URLSession.shared.dataTask(with:url){ data, response, error in
             let decoder = JSONDecoder()
             if let data = data {
                 do {
                     let company_data = try decoder.decode(CompanyData.self, from:data)
                     
                      DispatchQueue.main.async{
                          self.company_data = [company_data]
                      }
                    
                     print(company_data.businessSegments)
                     print()
                     print(company_data.companies)
                     print()
                     
                     
                 } catch {
                     print("cannot decode")
                     print(String(data:data, encoding:.utf8) as Any)
                     print(error)
                 }
             }
             
         }
         
         task.resume()
         
         
     }
 }

 
 

ContentView.swift

import SwiftUI

struct ContentView: View {
    @StateObject private var companyVM = CompanyViewModel()
    var body: some View {
        NavigationView{
            VStack {
                ForEach(companyVM.company_data,id:\.self){ item in
                    ForEach(item.businessSegments,id:\.self){ segment in
                        /*Text(segment.name)
                         .multilineTextAlignment(.center)
                         .bold()
                         .font(.custom("Montserrat-Bold", size: 24)) */
                        
                        
                        NavigationLink(destination:
                                        CompanyName(segment: segment.name)){
                            Text(segment.name)
                                .frame(width:240,height:50)
                                .bold()
                                .foregroundColor(.white)
                                .background(Color.orange)
                                .clipShape(Capsule())
                         }
                        
                        
                    }
                }
            }
            .padding()
            .onAppear(){
                companyVM.getUserData()
            }
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

CompanyName.swift

import SwiftUI

struct CompanyName: View {
    let segment: String
    @StateObject private var companyVM = CompanyViewModel()
    var body: some View {
        NavigationView{
            VStack{
                Text(segment)
                    .multilineTextAlignment(.center)
                    .bold()
                    .font(.custom("Montserrat-Bold", size: 24))
                
                ForEach(companyVM.company_data,id:\.self){ item in
                    ForEach(item.companies,id:\.self){ company in
                        Text(company.name)
                            .multilineTextAlignment(.center)
                            .bold()
                            .font(.custom("Montserrat-Bold", size: 24))
                    }
                }
                
            }.padding()
                .onAppear(){
                    companyVM.getUserData()
                }
        }
    }
}
    struct CompanyName_Previews: PreviewProvider {
        static var previews: some View {
            CompanyName(segment: "Business Segments")
        }
    }


答案1

得分: 0

以下是显示与所选业务领域相关的公司的代码部分的翻译:

这是显示与所选业务领域相关的公司的代码。
当您点击一个业务领域时,将检索该特定业务领域的公司(基于id
来自; 特定的 `CompanyData` 或来自所有 `[CompanyData]`。请调整代码以
选择其中一个,`CompanyViewModel` 中提供了这两个函数。

注意,我保留了 `@Published var company_data: [CompanyData]`
尽管您说其中只有一个 `CompanyData`

请查看此链接,它提供了如何使用 `ObservableObject` 并在您的应用程序中管理数据的示例 https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

class CompanyViewModel: ObservableObject {
    @Published var company_data: [CompanyData] = []
    
    func getUserData(){
        guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
            print("无效的URL")
            return
        }
        let task = URLSession.shared.dataTask(with:url){ data, response, error in
            let decoder = JSONDecoder()
            if let data = data {
                do {
                    let company_data = try decoder.decode(CompanyData.self, from:data)
                    DispatchQueue.main.async{
                        self.company_data = [company_data]
                    }
                    print(company_data.businessSegments)
                    print()
                    print(company_data.companies)
                    print()
                } catch {
                    print("无法解码")
                    print(String(data:data, encoding:.utf8) as Any)
                    print(error)
                }
            }
        }
        task.resume()
    }
    
    // 获取特定业务领域和特定 CompanyData 中的所有公司
    func getCompaniesFor(seg: BusinessSegment, item: CompanyData) -> [BusinessSegment] {
        var companies = [BusinessSegment]()
        if let segCompanies = seg.companies {
            for id in segCompanies {
                for company in item.companies {
                    if company.id == id {
                        companies.append(company)
                    }
                }
            }
        }
        return companies
    }
    
    // 获取所有 [CompanyData] 中特定业务领域的所有公司
    func getAllCompaniesFor(seg: BusinessSegment) -> [BusinessSegment] {
        var companies = [BusinessSegment]()
        if let segCompanies = seg.companies {
            company_data.forEach { company_data in
                for company in company_data.companies {
                    for id in segCompanies {
                        if company.id == id {
                            companies.append(company)
                        }
                    }
                }
            }
        }
        return companies
    }
}

struct ContentView: View {
    @StateObject var companyVM = CompanyViewModel()
    
    var body: some View {
        NavigationView{
            VStack {
                ForEach(companyVM.company_data){ item in
                    ForEach(item.businessSegments){ segment in
                        NavigationLink(destination:
                                        CompanyName(segment: segment, companyVM: companyVM)){
                            Text(segment.name)
                                .frame(width:240,height:50)
                                .bold()
                                .foregroundColor(.white)
                                .background(Color.orange)
                                .clipShape(Capsule())
                        }
                    }
                }
            }
            .padding()
            .onAppear {
                companyVM.getUserData()
            }
        }
    }
}

struct CompanyName: View {
    let segment: BusinessSegment
    @ObservedObject var companyVM: CompanyViewModel
    
    var body: some View {
        NavigationView{
            VStack{
                Text(segment.name).foregroundColor(.blue)
                    .multilineTextAlignment(.center)
                    .bold()
                    .font(.custom("Montserrat-Bold", size: 24))
                
                ForEach(companyVM.getAllCompaniesFor(seg: segment)){ company in
                    Text(company.name)
                        .multilineTextAlignment(.center)
                        .bold()
                        .font(.custom("Montserrat-Bold", size: 24))
                }
                
            }.padding()
        }
    }
}

// MARK: - CompanyData
struct CompanyData: Identifiable, Codable, Hashable {
    let id = UUID()
    let client: Client
    let businessSegments, companies: [BusinessSegment]
    
    enum CodingKeys: String, CodingKey {
        case client, companies
        case businessSegments = "business_segments"
    }
}

// MARK: - BusinessSegment
struct BusinessSegment: Identifiable, Codable, Hashable {
    let id: Int
    let name: String
    let status: String
    let companies: [Int]?
}

// MARK: - Client
struct Client: Identifiable, Codable, Hashable {
    let id: Int
    let firstName, lastName, email: String
    
    enum CodingKeys: String, CodingKey {
        case id, email
        case firstName = "first_name"
        case lastName = "last_name"
    }
}
英文:

Here is the code that displays the companies related to the selected segment.
As you tap a segment, the companies for that particular segment are retrieved (based on id)
from; a particular CompanyData or from all [CompanyData]. Adjust the code to
select one or the other, both functions are presented in the CompanyViewModel.

Note, I left the @Published var company_data: [CompanyData],
although you said you only have one CompanyData in it.

Have a look at this link, it gives you examples of how to use ObservableObject and manage data in your app https://developer.apple.com/documentation/swiftui/managing-model-data-in-your-app

class CompanyViewModel: ObservableObject {
@Published var company_data: [CompanyData] = []
func getUserData(){
guard let url = Bundle.main.url(forResource:"Company", withExtension:"json") else {
print("Invalid URL")
return
}
let task = URLSession.shared.dataTask(with:url){ data, response, error in
let decoder = JSONDecoder()
if let data = data {
do {
let company_data = try decoder.decode(CompanyData.self, from:data)
DispatchQueue.main.async{
self.company_data = [company_data]
}
print(company_data.businessSegments)
print()
print(company_data.companies)
print()
} catch {
print("cannot decode")
print(String(data:data, encoding:.utf8) as Any)
print(error)
}
}
}
task.resume()
}
// get all companies for a particular segment and from a particular CompanyData
func getCompaniesFor(seg: BusinessSegment, item: CompanyData) -> [BusinessSegment] {
var companies = [BusinessSegment]()
if let segCompanies = seg.companies {
for id in segCompanies {
for company in item.companies {
if company.id == id {
companies.append(company)
}
}
}
}
return companies
}
// get all companies for a particular segment from all [CompanyData]
func getAllCompaniesFor(seg: BusinessSegment) -> [BusinessSegment] {
var companies = [BusinessSegment]()
if let segCompanies = seg.companies {
company_data.forEach { company_data in
for company in company_data.companies {
for id in segCompanies {
if company.id == id {
companies.append(company)
}
}
}
}
}
return companies
}
}
struct ContentView: View {
@StateObject var companyVM = CompanyViewModel() // <-- here
var body: some View {
NavigationView{
VStack {
ForEach(companyVM.company_data){ item in
ForEach(item.businessSegments){ segment in
/*Text(segment.name)
.multilineTextAlignment(.center)
.bold()
.font(.custom("Montserrat-Bold", size: 24)) */
// --- here
NavigationLink(destination:
CompanyName(segment: segment, companyVM: companyVM)){
Text(segment.name)
.frame(width:240,height:50)
.bold()
.foregroundColor(.white)
.background(Color.orange)
.clipShape(Capsule())
}
}
}
}
.padding()
.onAppear {
companyVM.getUserData()
}
}
}
}
struct CompanyName: View {
let segment: BusinessSegment  // <-- here
@ObservedObject var companyVM: CompanyViewModel // <-- here
var body: some View {
NavigationView{
VStack{
Text(segment.name).foregroundColor(.blue)
.multilineTextAlignment(.center)
.bold()
.font(.custom("Montserrat-Bold", size: 24))
// --- here
ForEach(companyVM.getAllCompaniesFor(seg: segment)){ company in
Text(company.name)
.multilineTextAlignment(.center)
.bold()
.font(.custom("Montserrat-Bold", size: 24))
}
}.padding()
}
}
}
// MARK: - CompanyData
struct CompanyData: Identifiable, Codable,Hashable { // <-- here
let id = UUID() // <-- here
let client: Client
let businessSegments, companies: [BusinessSegment]
enum CodingKeys: String, CodingKey {
case client, companies
case businessSegments = "business_segments"
}
}
// MARK: - BusinessSegment
struct BusinessSegment: Identifiable, Codable,Hashable { // <-- here
let id: Int
let name: String
let status: String
let companies: [Int]?
}
// MARK: - Client
struct Client: Identifiable, Codable,Hashable { // <-- here
let id: Int
let firstName, lastName, email: String
enum CodingKeys: String, CodingKey {
case id, email
case firstName = "first_name"
case lastName = "last_name"
}
}

答案2

得分: 0

根据之前的回答,我已经在等待新的回复时找到了我的下一个问题:
代码如下:

func getAllCompaniesFor(seg: BusinessSegment, com: [Companies]) -> [Companies] {
    var companies = [Companies]()
    print(companies)
    if let segCompanies = seg.companies {
        
        company_data.forEach { company_data in
            for company in company_data.companies {
                for id in segCompanies {
                    if company.id == id {
                        companies.append(company)
                        print(companies)
                    }
                }
            }
        }
    }
    return companies
}

请注意,代码部分已经被保留,没有进行翻译。

英文:

Based on the previous answer, I have already figured out my following question as I waited for a new response:
the code is like this

 func getAllCompaniesFor(seg: BusinessSegment, com: [Companies]) -> [Companies] {
var companies = [Companies]()
print(companies)
if let segCompanies = seg.companies {
company_data.forEach { company_data in
for company in company_data.companies {
for id in segCompanies {
if company.id == id {
companies.append(company)
print(companies)
}
}
}
}
}
return companies
}

huangapple
  • 本文由 发表于 2023年1月9日 11:08:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052850.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定