Manos Chorianopoulos

fix context response parsing

......@@ -1156,6 +1156,86 @@ if self.isUserAuthenticated() {
**Result**: ✅ **No more ERROR: -1** - campaigns load successfully for both authenticated and non-authenticated users
---
#### **Issue #8: Central Context Response Parsing (FINAL SOLUTION)**
**File**: `SwiftWarplyFramework/SwiftWarplyFramework/Network/NetworkService.swift`
**Problem**: All context endpoints failed due to incorrect response structure parsing - looking for data at wrong level
**Impact**: ❌ **CRITICAL** - Multiple endpoints failing with ERROR: -1 due to response parsing issues
**Root Cause**: The server returns responses in format `{"status": "1", "context": {...}}` but the code expected data at top level.
**Example Response Structure**:
```json
{
"status": "1",
"context": {
"MAPP_CAMPAIGNING-status": 1,
"MAPP_CAMPAIGNING": { "campaigns": [...] },
"events_processed": 1
}
}
```
**Solution**: **Central Response Transformation in NetworkService**
```swift
/// Transform context-wrapped responses to flatten structure for backward compatibility
private func transformContextResponse(_ response: [String: Any]) -> [String: Any] {
// Detect context response pattern: {"status": "1", "context": {...}}
if let statusString = response["status"] as? String,
let context = response["context"] as? [String: Any] {
print("🔄 [NetworkService] Detected context response - transforming structure")
// Start with context content
var transformedResponse = context
// Convert string status to integer for backward compatibility
transformedResponse["status"] = (statusString == "1") ? 1 : 0
// Preserve any other top-level fields (like events_processed)
for (key, value) in response {
if key != "context" && key != "status" {
transformedResponse[key] = value
}
}
return transformedResponse
}
// Return unchanged if not a context response
return response
}
```
**Integration**: Added to `requestRaw` method in NetworkService:
```swift
public func requestRaw(_ endpoint: Endpoint) async throws -> [String: Any] {
let data = try await performRequest(endpoint)
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
throw NetworkError.invalidResponse
}
// Transform context-wrapped responses for backward compatibility
let transformedResponse = transformContextResponse(json)
return transformedResponse
} catch {
throw NetworkError.decodingError(error)
}
}
```
**Key Benefits**:
1. **Central Fix** - One solution fixes all context endpoints automatically
2. **Smart Detection** - Automatically detects context responses vs regular responses
3. **Backward Compatible** - Non-context responses pass through unchanged
4. **Future-Proof** - New context endpoints work automatically
5. **Zero Breaking Changes** - All existing code continues to work
**Result**: ✅ **Universal fix for all context response parsing issues** - getCampaigns and all other context endpoints now work correctly
---
### **🔧 Additional Safety Fixes - June 27, 2025 (Session 2)**
After the initial legacy credential removal, a comprehensive search revealed **3 additional problematic checks** that could still cause issues:
......
......@@ -141,7 +141,10 @@ public final class NetworkService: NetworkServiceProtocol {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
throw NetworkError.invalidResponse
}
return json
// Transform context-wrapped responses for backward compatibility
let transformedResponse = transformContextResponse(json)
return transformedResponse
} catch {
throw NetworkError.decodingError(error)
}
......@@ -177,6 +180,39 @@ public final class NetworkService: NetworkServiceProtocol {
// MARK: - Private Methods
/// Transform context-wrapped responses to flatten structure for backward compatibility
/// Detects responses with pattern: {"status": "1", "context": {...}} and flattens them
private func transformContextResponse(_ response: [String: Any]) -> [String: Any] {
// Detect context response pattern: {"status": "1", "context": {...}}
if let statusString = response["status"] as? String,
let context = response["context"] as? [String: Any] {
print("🔄 [NetworkService] Detected context response - transforming structure")
// Start with context content
var transformedResponse = context
// Convert string status to integer for backward compatibility
transformedResponse["status"] = (statusString == "1") ? 1 : 0
// Preserve any other top-level fields (like events_processed)
for (key, value) in response {
if key != "context" && key != "status" {
transformedResponse[key] = value
}
}
print("✅ [NetworkService] Context response transformed successfully")
print(" Original keys: \(Array(response.keys).sorted())")
print(" Transformed keys: \(Array(transformedResponse.keys).sorted())")
return transformedResponse
}
// Return unchanged if not a context response
return response
}
private func performRequest(_ endpoint: Endpoint) async throws -> Data {
// Check network connectivity
guard isConnected else {
......