在 URL 会话中获取嵌套的 json?
Get a nested json in URL session?
{
"data":{
"email":"ms.lightwave@example.com",
"password":"123",
"token":""
}
}
struct JsonResult: View{
@State private var results = [GetData]()
var body: some View{
List(results, id: \.email){ item in
VStack(alignment: .leading) {
Text(item.password)
.font(.headline)
Text(item.token)
.font(.headline)
}
}.task {
await loadData()
}
}
struct Response : Codable {
var results: [GetData]
}
struct GetData: Codable{
var data : [Result]
}
struct Result: Codable {
var email: String
var password: String
var token: String
}
func loadData() async{
guard let url = URL(string: "MYURL") else {
print("invalid URL")
return
}
do{
let(data,_) = try await URLSession.shared.data(from: url)
// more code
if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data)
{
results = decodedResponse.results
}
} catch {
print("Invalid Data")
}
}
}
我需要知道根据我提供的数据结构,可编码结构是否正确?还有列表中的获取?请在 URLsession 中需要帮助我还是新手,我对 url 几乎一无所知!
如果你能帮助我,我将不胜感激!非常感谢你 !!!!
struct Response : Decodable, Hashable {
var results: [GetData]
}
struct GetData: Decodable, Hashable{
var data : [Result]
}
struct Result: Decodable, Hashable {
var email: String
var password: String
var token: String
}
enum RequestError: Error {
case invalidURL
case missingData
}
class JsonResultViewModel: ObservableObject{
@Published var response = [Response]()
func performHTTPRequest(urlString: String) async throws{
guard let url = URL(string: urlString) else {throw RequestError.invalidURL}
guard let (data, resp) = try? await URLSession.shared.data(from: url) else{throw RequestError.invalidURL}
guard (resp as? HTTPURLResponse)?.statusCode == 200 else {throw RequestError.invalidURL}
let decoder = JSONDecoder()
guard let jsonResponse = try? decoder.decode([Response].self, from: data) else {throw RequestError.missingData}
DispatchQueue.main.async {
self.response = jsonResponse
}
}
}
struct ContentView: View {
@StateObject private var results = JsonResultViewModel()
var body: some View {
List(results.response.indices, id: \.self){ index in
VStack(alignment: .leading) {
Text(results.response[index].results[index].data[index].email)
.font(.headline)
Text(results.response[index].results[index].data[index].token)
.font(.headline)
}
}
.onAppear(perform: {
Task{
do {
try await results.performHTTPRequest(urlString: "wwww.url.com")
} catch RequestError.invalidURL{
print("invalid URL")
} catch RequestError.missingData{
print("missing data")
}
}
})
}
}
在 JSON 中没有涉及数组(根本没有 []
)。
JSON对应的机型是
struct Response: Decodable {
let data : UserData
}
struct UserData: Decodable {
let email: String
let password: String
let token: String
}
所以数据源不能声明为数组。要避免可选类型,请创建一个枚举,其关联值指示 state。好处是可以根据状态显示不同的视图
struct JsonResult: View {
enum LoadingState {
case idle, loading, loaded(UserData), failure(Error)
}
这是结构的其余部分,请考虑也没有 List
因为 UserData
是单个对象。
@State private var state : LoadingState = .idle
var body: some View {
VStack {
switch state {
case .idle: EmptyView()
case .loading: ProgressView()
case .loaded(let userData):
VStack(alignment: .leading) {
Text(userData.password)
.font(.headline)
Text(userData.email)
.font(.headline)
}
case .failure(let error): Text(error.localizedDescription)
}
}.task {
await loadData()
}
}
func loadData() async {
state = .loading
guard let url = URL(string: "MYURL") else {
state = .failure(URLError(.badURL))
return
}
do {
let (data,_) = try await URLSession.shared.data(from: url)
// more code
let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
state = .loaded(decodedResponse.data)
} catch {
state = .failure(error)
print(error) // this shows the real DecodingError
}
}
}
{
"data":{
"email":"ms.lightwave@example.com",
"password":"123",
"token":""
}
}
struct JsonResult: View{
@State private var results = [GetData]()
var body: some View{
List(results, id: \.email){ item in
VStack(alignment: .leading) {
Text(item.password)
.font(.headline)
Text(item.token)
.font(.headline)
}
}.task {
await loadData()
}
}
struct Response : Codable {
var results: [GetData]
}
struct GetData: Codable{
var data : [Result]
}
struct Result: Codable {
var email: String
var password: String
var token: String
}
func loadData() async{
guard let url = URL(string: "MYURL") else {
print("invalid URL")
return
}
do{
let(data,_) = try await URLSession.shared.data(from: url)
// more code
if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data)
{
results = decodedResponse.results
}
} catch {
print("Invalid Data")
}
}
}
我需要知道根据我提供的数据结构,可编码结构是否正确?还有列表中的获取?请在 URLsession 中需要帮助我还是新手,我对 url 几乎一无所知!
如果你能帮助我,我将不胜感激!非常感谢你 !!!!
struct Response : Decodable, Hashable {
var results: [GetData]
}
struct GetData: Decodable, Hashable{
var data : [Result]
}
struct Result: Decodable, Hashable {
var email: String
var password: String
var token: String
}
enum RequestError: Error {
case invalidURL
case missingData
}
class JsonResultViewModel: ObservableObject{
@Published var response = [Response]()
func performHTTPRequest(urlString: String) async throws{
guard let url = URL(string: urlString) else {throw RequestError.invalidURL}
guard let (data, resp) = try? await URLSession.shared.data(from: url) else{throw RequestError.invalidURL}
guard (resp as? HTTPURLResponse)?.statusCode == 200 else {throw RequestError.invalidURL}
let decoder = JSONDecoder()
guard let jsonResponse = try? decoder.decode([Response].self, from: data) else {throw RequestError.missingData}
DispatchQueue.main.async {
self.response = jsonResponse
}
}
}
struct ContentView: View {
@StateObject private var results = JsonResultViewModel()
var body: some View {
List(results.response.indices, id: \.self){ index in
VStack(alignment: .leading) {
Text(results.response[index].results[index].data[index].email)
.font(.headline)
Text(results.response[index].results[index].data[index].token)
.font(.headline)
}
}
.onAppear(perform: {
Task{
do {
try await results.performHTTPRequest(urlString: "wwww.url.com")
} catch RequestError.invalidURL{
print("invalid URL")
} catch RequestError.missingData{
print("missing data")
}
}
})
}
}
在 JSON 中没有涉及数组(根本没有 []
)。
JSON对应的机型是
struct Response: Decodable {
let data : UserData
}
struct UserData: Decodable {
let email: String
let password: String
let token: String
}
所以数据源不能声明为数组。要避免可选类型,请创建一个枚举,其关联值指示 state。好处是可以根据状态显示不同的视图
struct JsonResult: View {
enum LoadingState {
case idle, loading, loaded(UserData), failure(Error)
}
这是结构的其余部分,请考虑也没有 List
因为 UserData
是单个对象。
@State private var state : LoadingState = .idle
var body: some View {
VStack {
switch state {
case .idle: EmptyView()
case .loading: ProgressView()
case .loaded(let userData):
VStack(alignment: .leading) {
Text(userData.password)
.font(.headline)
Text(userData.email)
.font(.headline)
}
case .failure(let error): Text(error.localizedDescription)
}
}.task {
await loadData()
}
}
func loadData() async {
state = .loading
guard let url = URL(string: "MYURL") else {
state = .failure(URLError(.badURL))
return
}
do {
let (data,_) = try await URLSession.shared.data(from: url)
// more code
let decodedResponse = try JSONDecoder().decode(Response.self, from: data)
state = .loaded(decodedResponse.data)
} catch {
state = .failure(error)
print(error) // this shows the real DecodingError
}
}
}