Chris
Chris

Reputation: 29

JSONSerialization makes incorrect JSON object. Swift

I'm creating an iOS app that connects to a NodeJS server. The get method works fine but the POST method has problems.

var urlRequest = URLRequest(url: "http://localhost:3000/register")
urlRequest.httpMethod = "POST"
let info: [String:Any] = ["username": "username", "password":"username", "email":"[email protected]"]
do {
    let jsonInfo = try 
    JSONSerialization.data(withJSONObject: info, options[])
    urlRequest.httpBody = jsonInfo
} catch {
    print("ERROR")
    return
}

The request gets sent but something goes wrong with JSONSerialization because this is the JSON data that the server gets: {'{"email":"[email protected]","username":"username","password":"username"}': '' }

This is what I'm going for: {"email":"[email protected]","username":"username","password":"username"}

This is part of the server code:

const express = require('express');
const bodyParser = require('body-parser');
var app = express();
var allowMethods = function(req, res, next) {
res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, PUT, DELETE');
next();
}
http.createServer(app).listen(3001);
console.log("Server started");
app.use(bodyParser.urlencoded({extended: true}));
app.use(allowMethods);

const _ = require('lodash');
let b = _.pick(req.body, ['username', 'password', 'email']);

Any ideas on what I'm doing wrong? I'd like to avoid using alamofire if possible. I've tried changing the format of the dictionary but always turns out as:

{ 'the whole dictionary is the key': ''}

I've also tried using pretty print and this was the result:

{ '{\n  "email" : "[email protected]",\n  "username" : "username",\n  "password" : "username"\n}': '' }

Any help is appreciated. Thank you!

EDIT:

I tried Mike Taverne's suggestions. I changed the server code to use this instead:

app.use(bodyParser.json());

But I receive an empty body from the simulator. I also added these to the swift code:

urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")

But the server also receives an empty body and by empty body I mean the data I'm trying to send is received as empty by the server. When I check the httpBody the data is there but for some reason the server doesn't receive it.

Upvotes: 1

Views: 443

Answers (2)

Chris
Chris

Reputation: 29

I solved it by changing the data itself. Instead of forcing it to pass JSON I passed it as a string encoded using UTF8

let dataString = "username=username&password=username&[email protected]"
urlRequest.httpBody = dataString.data(using: .utf8)

I got the answer by using the method in this post: HTTP Request in Swift with POST method

Upvotes: 0

Mike Taverne
Mike Taverne

Reputation: 9362

I believe your Swift code is fine. When I did this in a playground:

print(String(data: urlRequest.httpBody!, encoding: String.Encoding.utf8)!)

It printed:

{"username":"username","password":"username","email":"[email protected]"}

I'm not an expert on body-parser, but I think that instead of this:

bodyParser.urlencoded({extended: true})

You should be using this:

bodyParser.json([options]) //not sure which options exactly you need

You may need to set Content-Type: application/json header as well. Refer to the body-parser documentation for more info.

Upvotes: 1

Related Questions