Reputation: 369
I'm using the NSURLSession delegate way of making http get request to get json data from a server. I end up passing in the NSData received in my NSURLSessionDataDelegate to a model object to update an array like so:
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
networkDelegate?.updateGameList(data)
dataTask.resume()
}
Once the data makes its way into the updateGameList function, weird stuff happens if I try to use NSJSONSerialization.JSONObjectWithData. If I don't try to use NSJSONSerialization, and merely convert the NSData to a string, it looks like the proper response I am expecting, something like this:
Optional([{"id":"a19610e4-675e-40b3-8335-085b61bfb0e3","name":"tttt","status":"PLAYING"},
{"id":"3be2e411-0086-46fd-8fc9-38d11831d0fb","name":"LWP TEST","status":"PLAYING"},
{"id":"b5d97d73-1ce2-4e5b-8b38-805835e2a21d","name":"asd","status":"PLAYING"},
{"id":"8a15575c-4c2c-4b46-ad5b-51b4b2680416","name":"MsGame","status":"WAITING"},
{"id":"b54531b8-5323-4630-929c-6eb2cfebde63","name":"423","status":"PLAYING"},
{"id":"5a7cfaa0-e2a4-41f6-bda2-a854a2d00a57","name":"4234","status":"PLAYING"}])
However, once I try to use the NSData with NSJSONSerialization.JSONObjectWithData to make an NSArray, it starts throwing errors because the data seems to be truncated either at the beginning or end, like this:
Optional([{"id":"a19610e4-675e-40b3-8335-085b61bfb0e3","name":"tttt","status":"PLAYING"},{"id":"3be2e411-0086-46fd-8fc9-38d11831d0fb","name":"LWP TEST","status":"PLAYING"},
{"id":"6d4e9731-61be-4191-bb9a-a30b6395a4a2","name":"RANDOMBOT","status":"PLAYING"},{"id":"c31b363c-f565-4f4a-a6f1-1ac219425f40","name":"Testament ","status":"PLAYING"},
{"id":"af14d8bc-37a0-4ec3-88de-ee364344d720","name":"Testament ","status":"PLAYING"},
{"id":"29439dd9-357d-445b-856c-39862e19c2fc","name":"Testament ","status":"PLAYING"},{"id":"cc29046f-4e80-422d-a103-5be175e799c9","name":"matt7","status":"PLAYING"},
{"id":"ff75c546-0e9b-4560-8efb-d0fa5be61cde","name":"u","status":"DONE"},{"id":"3d88df55-6f84-469c-a18e-27e463dc30eb","name":"test","status":"PLAYING"},{"id":"40eb1b13-21c3-4c8d-a379-e6b85329374b","name":"test","status":"PLAYING"},
{"id":"4e7519dd-79d3-4229-8d0e-47ca112dc08f","name":"test","status":"PLAYING"},{"id":"32ce49cc-17aa-47ca-8b9f-1c35dbdb78e6","name":"test","status":"PLAYING"},
{"id":"f5d5c961-17eb-421d-86b1-fbbadfb795da","name":"test","status":"PLAYING")
update game list error Error Domain=NSCocoaErrorDomain Code=3840
"Unexpected end of file while parsing object."
UserInfo={NSDebugDescription=Unexpected end of file while parsing object.}
Here is the updateGameList function, when I comment out the do-catch block with the JSONSerialization code in it, the dataString prints out the correct response, when I uncomment it out, it runs multiple times, almost like it's trying to process the data a chunk at a time instead of all at once. If I take out the .AllowFragments option, it tells me to put it in, when I put it in, it gets to the real error of the json data not starting or ending correctly.
func updateGameList(gameListData:NSData) {
let dataString = NSString(data: gameListData, encoding: NSUTF8StringEncoding)
print(dataString)
do {
let gameList:NSArray = try NSJSONSerialization.JSONObjectWithData(gameListData, options: [.AllowFragments]) as! NSArray
}
catch {
print("update game list error \(error)")
}
}
Upvotes: 0
Views: 326
Reputation: 17844
Quoting from the documentation:
This delegate method may be called more than once, and each call provides only data received since the previous call. The app is responsible for accumulating this data if needed.
So what you're observing is a feature: the data is received in chunks (most likely because the originating server uses Transfer-Encoding: chunked
), and therefore you cannot expect to be able to parse each chunk individually - you'll have to accumulate all chunks to from one response, which you can then try to parse.
Upvotes: 1