如何在Swift中解析PHP脚本生成的HTTP请求JSON响应?
Hey there! Let's break this down into two clear parts: first fixing up your PHP script to output valid, secure JSON, then writing the Swift code to parse that response properly.
Your current PHP code is incomplete (the else block is missing) and has a critical SQL injection vulnerability. Let's fix both issues and ensure it outputs valid JSON every time:
<?php include "dbconnect.php"; // First, validate required POST parameters exist if (!isset($_POST['id']) || !isset($_POST['uname'])) { echo json_encode(['error' => 'Missing required parameters: id or uname']); exit; } $id = $_POST['id']; $uname = $_POST['uname']; try { // Use prepared statements to prevent SQL injection (critical!) $queryExistingBike = "SELECT StatoBici, Username FROM BICI INNER JOIN UTENTE ON utenteKEY = KEYutente WHERE IdBike = ?"; $stmt = $connection->prepare($queryExistingBike); $stmt->bind_param("s", $id); // Use "i" instead of "s" if IdBike is an integer $stmt->execute(); $result = $stmt->get_result(); $dati = $result->fetch_assoc(); if ($dati) { // Update Username field to "true"/"false" based on match $dati['Username'] = ($dati["Username"] === $uname) ? "true" : "false"; echo json_encode($dati); } else { echo json_encode(['error' => 'No bike found with that ID']); } } catch (Exception $ex) { echo json_encode(['error' => $ex->getMessage()]); } // Clean up database connections $stmt->close(); $connection->close(); ?>
The modern, type-safe way to parse JSON in Swift is using Codable. Here's a complete implementation:
1. Define a Model for Your JSON Response
Create a struct that matches the JSON structure from your PHP script:
struct BikeResponse: Codable { let statoBici: String? let username: String? let error: String? // Map PHP's camelCase keys to Swift's snake_case (or preferred naming) enum CodingKeys: String, CodingKey { case statoBici = "StatoBici" case username = "Username" case error } }
2. Write a Function to Fetch & Parse the Response
This function handles the HTTP POST request, receives the JSON, and parses it into your model:
func fetchBikeStatus(forId bikeId: String, username: String, completion: @escaping (Result<BikeResponse, Error>) -> Void) { guard let baseUrl = URL(string: "YOUR_PHP_SCRIPT_URL_HERE") else { completion(.failure(NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid server URL"]))) return } // Encode POST parameters safely to avoid special character issues guard let encodedId = bikeId.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let encodedUsername = username.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { completion(.failure(NSError(domain: "EncodingError", code: -2, userInfo: [NSLocalizedDescriptionKey: "Failed to encode parameters"]))) return } let postBody = "id=\(encodedId)&uname=\(encodedUsername)".data(using: .utf8) var request = URLRequest(url: baseUrl) request.httpMethod = "POST" request.httpBody = postBody request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") let task = URLSession.shared.dataTask(with: request) { data, response, error in // Handle network errors first if let networkError = error { completion(.failure(networkError)) return } // Ensure we received data guard let responseData = data else { completion(.failure(NSError(domain: "NoData", code: -3, userInfo: [NSLocalizedDescriptionKey: "No data received from server"]))) return } // Parse JSON into our model do { let decoder = JSONDecoder() let bikeResponse = try decoder.decode(BikeResponse.self, from: responseData) completion(.success(bikeResponse)) } catch { completion(.failure(error)) } } task.resume() }
3. Use the Function in Your Code
Call the function and handle the result:
// Example usage fetchBikeStatus(forId: "123", username: "francesco") { result in switch result { case .success(let response): if let errorMessage = response.error { print("Server error: \(errorMessage)") return } if response.username == "true" { print("User owns this bike! Status: \(response.statoBici ?? "Unknown")") } else { print("User does not own this bike.") } case .failure(let error): print("Request failed: \(error.localizedDescription)") } }
- SQL Injection Protection: Always use prepared statements in PHP (as shown) instead of directly inserting user input into SQL queries. This prevents malicious attacks.
- Type Safety: Using
Codableensures you don't have to deal with messy[String: Any]dictionaries and catches typos at compile time. - Error Handling: Both PHP and Swift code handle edge cases (missing parameters, no bike found, network errors) to avoid crashes.
- Parameter Encoding: Always URL-encode POST parameters to handle special characters (like spaces or symbols) correctly.
内容的提问来源于stack exchange,提问作者Francesco Gregori

