1

I have an application which records a video and saves it to Photos. I am trying to retrieve the saved video and post it to the server using an API. Here is my code for the same:

var request = URLRequest(url: URL(string: "SERVER_URL")!)
request.httpMethod = "POST"
request.setValue("multipart/form-data;", forHTTPHeaderField: "Content-Type")
var movieData: Data?
var JSONData: [String: Data]
do {
     movieData = try Data(contentsOf: url, options: Data.ReadingOptions.alwaysMapped)
     JSONData = ["live_video_file":movieData!]
} catch _ {
     movieData = nil
     return
}
var body = Data()
let datadata = try? JSONSerialization.data(withJSONObject: JSONData)
body.append(datadata!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
     if let `error` = error {
          print(error)
          return
     }
     if let `data` = data {
          print(String(data: data, encoding: String.Encoding.utf8)!)
     }
}
task.resume()

The error I receive when I post the data is:

2020-06-13 00:40:01.831576+0530 FaceVision[3778:1193943] [xpc.exceptions] <NSXPCConnection: 0x2820f1710> connection to service on pid 260 named com.apple.photos.service: Exception caught during invocation of reply block to message 'applyChangesRequest:reply:'.

Ignored Exception: Invalid type in JSON write (Foundation.__NSSwiftData)
(
    0   CoreFoundation                      0x0000000195e7c314 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 1254164
    1   libobjc.A.dylib                     0x0000000195b90c1c objc_exception_throw + 60
    2   Foundation                          0x00000001962f8e90 19FAB59F-6527-3245-85BB-905FD4255CDE + 1859216
    3   Foundation                          0x00000001962fb8ac 19FAB59F-6527-3245-85BB-905FD4255CDE + 1869996
    4   libswiftCore.dylib                  0x00000001a3946ec4 DFF781B2-A7E7-3050-AC01-8D682E7E2D75 + 2911940
    5   libswiftCore.dylib                  0x00000001a370b794 DFF781B2-A7E7-3050-AC01-8D682E7E2D75 + 571284
    6   Foundation                          0x00000001962fad94 19FAB59F-6527-3245-85BB-905FD4255CDE + 1867156
    7   Foundation                          0x00000001961a3be0 19FAB59F-6527-3245-85BB-905FD4255CDE + 461792
    8   Foundation                          0x00000001961a384c 19FAB59F-6527-3245-85BB-905FD4255CDE + 460876
    9   FaceVision                          0x000000010263deb0 $s10FaceVision14ViewControllerC9saveVideo3url16returnCompletiony10Foundation3URLV_ySSSgctFZySo21PHAuthorizationStatusVcfU_ySb_s5Error_pSgtcfU0_ + 2032
    10  FaceVision                          0x000000010263f194 $sSbs5Error_pSgIegyg_SbSo7NSErrorCSgIeyByy_TR + 140
    11  Photos                              0x00000001a184bbbc 2459BA77-F19F-31BA-A85E-3713FFAEEAE3 + 883644
    12  CoreFoundation                      0x0000000195e82f14 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 1281812
    13  CoreFoundation                      0x0000000195d4c098 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 8344
    14  Foundation                          0x000000019637ed20 19FAB59F-6527-3245-85BB-905FD4255CDE + 2407712
    15  Foundation                          0x0000000196147600 19FAB59F-6527-3245-85BB-905FD4255CDE + 83456
    16  Foundation                          0x0000000196380058 19FAB59F-6527-3245-85BB-905FD4255CDE + 2412632
    17  libxpc.dylib                        0x0000000195a7e4f4 33B9156A-9AE1-3385-BD08-38552A3F3B7F + 103668
    18  libxpc.dylib                        0x0000000195a724d4 33B9156A-9AE1-3385-BD08-38552A3F3B7F + 54484
    19  libdispatch.dylib                   0x00000001029c7214 _dispatch_client_callout3 + 20
    20  libdispatch.dylib                   0x00000001029e3b54 _dispatch_mach_msg_async_reply_invoke + 392
    21  libdispatch.dylib                   0x00000001029ce798 _dispatch_lane_serial_drain + 260
    22  libdispatch.dylib                   0x00000001029cf5b4 _dispatch_lane_invoke + 492
    23  libdispatch.dylib                   0x00000001029db0f0 _dispatch_workloop_worker_thread + 1344
    24  libsystem_pthread.dylib             0x0000000195b83714 _pthread_wqthread + 276
    25  libsystem_pthread.dylib             0x0000000195b899c8 start_wqthread + 8
)

Why am I receiving this error and what can I do to prevent it?

1 Answers1

0

I'm assuming you are crashing in the call to JSONSerialization.data(withJSONObject:). If you read the docs on JSONSerialization, they say:

A Foundation object that may be converted to JSON must have the following properties:

The top level object is an NSArray or NSDictionary.

All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull.

All dictionary keys are instances of NSString.

Numbers are not NaN or infinity.

Other rules may apply. Calling isValidJSONObject(_:) or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.

The key bit is this: "All objects are instances of NSString, NSNumber, NSArray, NSDictionary, or NSNull". You are attempting to encode a dictionary containing a Data object, but Data is not one of the valid data types for JSON encoding.

Why do you think you need to JSON encode your video file? That seems odd.

If you do need to JSON encode it, you'll need to convert your video data to a Base64 encoded string, or somehow convert it to one of the above types.

What format does the server expect? Do you have a link to the server API spec?

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • The code isn't crashing on the ```JSONSerialization.data(withJSONObject:)``` I tried calling the same API using a different method. I'll link the method to you (it was an answer I found on StackOverflow) if need be, and had previously gotten the same error. This has something to do purely with sending the video as when I called the same API in the same structure, just without any video data, I did not receive any error. Thanks – Rahul Holani Jun 12 '20 at 19:31
  • So which line IS it crashing on then? And yes, if you don't try to send binary data, you won't crash. Video data is binary data, and you can't convert binary data to JSON directly. – Duncan C Jun 12 '20 at 19:33
  • Debugged the code. Turns out it was breaking on the ```JSONSerialization.data(withJSONObject:)``` part. I need to convert a dictionary of type ```[String: Data]``` to ```Data``` in order for it to be sent as a ```httpBody``` parameter of the request. What do you suggest I do if not ```JSONSerialization.data(withJSONObject:)``` @DuncanC – Rahul Holani Jun 12 '20 at 19:43
  • Just attach the file data as Data. Skip the JSON Encoding entirely. `request.httpBody = movieData`. – Duncan C Jun 12 '20 at 19:50
  • Need to assign httpBody with a key "live_video_feed" and a value of the video itself. Just a requirement from the back-end side of work. So, how can I assign a key to this line? ```movieData = try Data(contentsOf: url, options: Data.ReadingOptions.alwaysMapped)``` – Rahul Holani Jun 12 '20 at 19:59