英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论