Filtering a Remote Json List with SwiftUI

Hi,

My SwiftUI app is using json to populate a list. I had an array of the names of States that would link to a list of Congressional Representatives from the json file.

When I had the json file stored in my app I was able to filter the results in the NavagationLink by using this below.

Code Block
List {
ForEach(self.States, id: \.self) { States in
NavigationLink(destination: HouseList(houseData: self.houseData.filter({ $0.stateFullName == States}))) {
              Text(States)
                   .fontWeight(.regular)
                    .font(.system(size: 14))
                    }
                }
            }.listStyle(GroupedListStyle())


Now I have moved the json file online so I can update it regularly, but I cannot use the same method to filter my results.

I tried to use the State name from the json file, but that creates duplicates base on how many reps that State has. I tried a method to remove the duplicate States, but now the link will only show a single representative.

Here is what I am using now.

Code Block
var set: Set<HouseData> = []
let orderedset = fetchHouse.houseData.filter { set.insert($0).inserted }
List(orderedset, id: \.self) { houseData in
NavigationLink(destination: HouseList(HouseData: houseData)) {
                Text(houseData.stateFullName)
                            .fontWeight(.regular)
                            .font(.system(size: 14))
                    }
            }.listStyle(GroupedListStyle())



Can you show enough code to investigate what's happening?
The whole code of your View and the definition of fetchHouse.houseData, and all other relevant parts.
Here is how I'm decoding the JSON:

Code Block
struct StatePollingData: Hashable, Decodable {
    var state: String
    var dates: String
    var pollster: String
    var officeType: String
    var DEM: Int
    var GOP: Int
    var IND: Int
    var url: String
    var hashValue: Int {
        return state.hashValue
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(state)
    }
    static func ==(lhs: StatePollingData, rhs: StatePollingData) -> Bool {
        return lhs.state == rhs.state
    }
}


Here is the code that I was using for the local JSON file:

Code Block
let houseData: [HouseData] =
    load("houseMemberData.json")
let senateData: [SenateData] =
    load("senateMemberData.json")
let statePollingData: [StatePollingData] =
    load("pollingStates.json")
func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
    let data: Data
  
    guard let url = URL(string: "https://raw.githubusercontent.com/mrboss302/Ballotics/master/testX")
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }
    do {
        data = try Data(contentsOf: url)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}


Here is the view that I was using with the local JSON:

Code Block
import SwiftUI
struct StatesListHouse: View {
    var houseData: [HouseData]
 let States = ["Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming"]
    var body: some View {
            List {
                Section(header: Text("U.S. House Members")) {
                ForEach(self.States, id: \.self) { States in
                    NavigationLink(destination: HouseList(houseData: self.houseData.filter({ $0.stateFullName == States}))) {
                        Text(States)
                            .fontWeight(.regular)
                            .font(.system(size: 14))
                    }
                }
                    
                }
                
            }.listStyle(GroupedListStyle())
    }
}
    
struct StatesListHouse_Previews: PreviewProvider {
    static var previews: some View {
        StatesListHouse(houseData: houseData)
    }
}

And here is the Navigation Destination View:

Code Block
import SwiftUI
struct HouseList: View {
    var houseData: [HouseData]
    var body: some View {
        List {
            ForEach(self.houseData, id: \.self) { houseData in
                HStack {
                    Rectangle()
                        .fill(Color(houseData.party))
                        .frame(width: 6, height: 26)
                        .offset(y: 1)       
                    VStack(alignment: .leading) {
                        Text("\(houseData.officialName)")
                            .fontWeight(.medium)
                            .font(.system(size: 14))
                        Text((houseData.party))
                            .font(.system(size: 12))
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }
                    Spacer()
                    VStack(alignment: .trailing) {
                        Text("\(houseData.district)-\(houseData.state) House District")
                            .font(.system(size: 12))
                            .fontWeight(.medium)
                            .font(.subheadline)
                        Text((houseData.stateFullName))
                            .font(.system(size: 12))
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }.listStyle(GroupedListStyle())
    }
}
struct HouseList_Previews: PreviewProvider {
    static var previews: some View {
        HouseList(houseData: houseData)
    }
}




So the code above works. After making the JSON file remote I'm no longer about to the filter the list. Here is the code I'm using for the remote JSON file:

Code Block
public class HouseFetcher: ObservableObject {
@Published var houseData = [HouseData]()
init(){
load()
}
func load() {
let url = URL(string: "https://raw.githubusercontent.com/mrboss302/Ballotics/master/houseMemberData.json")!
URLSession.shared.dataTask(with: url) {(data,response,error) in
do {
if let d = data {
let decodedLists = try JSONDecoder().decode([HouseData].self, from: d)
DispatchQueue.main.async {
self.houseData = decodedLists
}
}else {
print("No Data")
}
} catch {
print ("Error")
}
}.resume()
}
}


Here I removed the States array since I could not use the filter to sort by the names of the states. So I tried using the names from the JSON, but now it creates duplicates base on how many House Reps that State has. I tried a method (orderedset in the code below) to remove the duplicate States, but now the link will only show a single representative.




Code Block
import SwiftUI
struct StatesListHouse: View {
    
    @ObservedObject var fetchHouse = HouseFetcher()
    
    var body: some View {
        var set: Set<HouseData> = []
        let orderedset = fetchHouse.houseData.filter { set.insert($0).inserted }
        
        List(orderedset, id: \.self) { houseData in
            NavigationLink(destination: HouseList(HouseData: houseData)) {
                Text(houseData.stateFullName)
                            .fontWeight(.regular)
                            .font(.system(size: 14))
                        
                    }
            }.listStyle(GroupedListStyle())
    }
}
struct StatesListHouse_Previews: PreviewProvider {
    static var previews: some View {
        StatesListHouse()
    }
}


Here the Navigation Destination View is mostly the same as the original except for the HouseData not being in brackets:

Code Block
import SwiftUI
struct HouseList: View {
    
    var HouseData: HouseData
    var body: some View {
        
        List { 
                HStack {
                    
                    Rectangle()
                        .fill(Color(HouseData.party))
                        .frame(width: 6, height: 26)
                        .offset(y: 1)
                    
                    VStack(alignment: .leading) {
                        
                        Text("\(HouseData.officialName)")
                            .fontWeight(.medium)
                            .font(.system(size: 14))
                        
                        
                        Text((HouseData.party))
                            .font(.system(size: 12))
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                        
                    }
                    
                    Spacer()
                    
                    VStack(alignment: .trailing) {
                        
                        Text("\(HouseData.district)-\(HouseData.state) House District")
                            .font(.system(size: 12))
                            .fontWeight(.medium)
                            .font(.subheadline)
                        
                        
                        Text((HouseData.stateFullName))
                            .font(.system(size: 12))
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                        
                    }
                    
                }
            
        }.listStyle(GroupedListStyle())
        
    }
}

Filtering a Remote Json List with SwiftUI
 
 
Q