JSON 使用 Alamofire 分块流式传输 Swift

JSON Streaming in chunks using Alamofire Swift

如何使用 Alamofire 请求获取流 JSON。我正在使用以下函数来获取响应

self.sessionManager?.request(url, method: methodType!, parameters: params, encoding: JSONEncoding.default, headers: headers)
            .validate()
            .responseJSON { (response) in
                if (response.result.error == nil) {
                    completion(response.result.value as AnyObject?, nil , response.response?.statusCode )
                } else {
                    // debugPrint("HTTP Request failed: \(String(describing: response.result.error))")
                    completion(nil, response.result.error, response.response?.statusCode)
                }
        }

还有我的 API Url 类似

http://{server Url}/services/data/{number of chunks}/{items in per chunk}

我从 API 得到的响应如果块的数量是 3 并且每个块的项目是 3

data: [
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026419,

    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    }
]

data: [
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    }
]

data: [
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    },
    {
        "invalidDraft": false,
        "bulkReserve": false,
        "srNo": 0,
        "returned": false,
        "status": "ACTIVE",
        "timestamp": 1580186026417,
    }
]

data:done

我没有从服务器收到任何响应,但在 Postman 中它工作正常。

您的请求失败的原因可能是您正在使用 responseJSON 解析响应,而响应似乎无效 json。

returned 数据由三个名为 data 的独立数组组成,都位于顶层。这应该如何转换为字典或数组?

是否可以更改服务器格式化响应的方式,例如 - 让它 return 一个顶层数组,有几个 data 子数组(每个块一个)?有点像这样:

[
    [
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026419
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        }
    ],
    [
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        }
    ],
    [
         {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        },
        {
            "invalidDraft": false,
            "bulkReserve": false,
            "srNo": 0,
            "returned": false,
            "status": "ACTIVE",
            "timestamp": 1580186026417
        }
    ]
]

如果这不可能,将响应解析为字符串,然后使用正则表达式查找字符串中的每个 "data" 数组,然后可以将其解析为 JSON。

要接收流式数据,您可以尝试添加

request.stream(closure: { data in ... })

在调用响应后,您应该在闭包内部从服务器收集数据块并最近解析它们。 在这种情况下,响应将为零。

所以它会是这样的:

let mData = NSMutableData()

self.sessionManager?
    .request(url, method: methodType!, parameters: params, encoding: JSONEncoding.default, headers: headers)
    .validate()       
    .stream(closure: { data in mData.append(data) })
    .response { response in
       //parse mData
    }

详细阐述 Alex 最有帮助的回答:

fileprivate lazy var alamoSession: Session = {
    let configuration = URLSessionConfiguration.default
    configuration.timeoutIntervalForRequest = 20
    configuration.urlCache?.removeAllCachedResponses()
    return Alamofire.Session(configuration: configuration /*, interceptor: interceptor*/)
}()

fileprivate func alamofireChunked () {

    guard let url = URL(string: "http://A_Steaming_Source.com")    // Put your datasource here
    else {
        return
    }
    let urlRequest = URLRequest(url: url)

    alamoSession.streamRequest(urlRequest).validate().responseStream { response in
        if let data = response.value {
            print("received \(data.count) bytes")
            if data.count > 0 {
                // process received data here
            }
        } else {
            switch response.event {
            case .complete( _):
                // perform any post processing here
                print("stream is finished")
                break;
            default:
                break;
            }
        }
    }
}