Request error Google Cloud NLP API with Swift - swift

I am trying to make a request to Google Cloud NLP API to obtain sentiment analysis for a piece of text. I used Postman to design the correct request, and I was able to get a valid response using Postman. However, when I try to make the same request from Swift, it gives me an error. The error and code snippet used to make the request is shown below.
func sendAPIRequest(with text: String){
print("Text: ", text)
let jsonRequest = [
[
"document":[
"type":"PLAIN_TEXT",
"language": "EN",
"content":"'Lawrence of Arabia' is a highly rated film biography about British Lieutenant T. E. Lawrence. Peter O'Toole plays Lawrence in the film."
],
"encodingType":"UTF8"
]
]
let jsonObject = JSON(jsonRequest)
let headers: HTTPHeaders = [
"X-Ios-Bundle-Identifier": "\(Bundle.main.bundleIdentifier ?? "") ",
"Content-Type": "application/json"
]
let APIRequest = Alamofire.request("https://language.googleapis.com/v1/documents:analyzeSentiment?key=\(gCloudAPIKey)", method: .post , parameters: jsonRequest as? [String: Any], encoding: JSONEncoding.default , headers: headers).responseJSON { (response) in
print(response)
if let json = response.result.value {
print("JSON: \(json)")
}
}
Error:
JSON: {
error = {
code = 400;
details = (
{
"#type" = "type.googleapis.com/google.rpc.BadRequest";
fieldViolations = (
{
description = "Must have some text content to annotate.";
field = "document.content";
}
);
}
);
message = "One of content, or gcs_content_uri must be set.";
status = "INVALID_ARGUMENT";
};
}

Sorry. Solved it. My jsonRequest should be of type Parameters according to Alamofire.
let jsonRequest: Parameters =
[
"document":[
"type":"PLAIN_TEXT",
"language": "EN",
"content":"\(text)"
],
"encodingType":"UTF8"
]

Related

Getting a 400 for my AFNetworking get call

I am using AFNetworking for the first time and attempting to make a get call using the FourSquare Places API. When I test with the endpoint on FourSquare's documentation website, my url with params works, but not with AFNetworking code. I keep getting a 400.
func findCoffee(coordinate: CLLocationCoordinate2D) {
let url = "https://api.foursquare.com/v2/venues/explore"
let params = [
"ll": "\(coordinate.latitude),\(coordinate.longitude)",
"intent": intent,
"limit": limit,
"client_id": "\(clientId)",
"client_secret": "\(clientSecret)"
]
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.get(url, parameters: params, success: { (operation, responseObject) in
}) { (operation, error) in
}
}

How to post parameter with (+ plus sign) in Alamofire

when post A+ or O+ or any (+) bloods types with + character, I receive a "not valid blood" error.
The blood value is in JSON dictionary: How do I post + character in Alamofire?
let dictionary = ["fname": "name",
"lname": "family",
"blood": "A+"]
let updateData = try! JSONEncoder().encode(dictionary)
let jsonString = String(data: updateData, encoding: .utf8)!
var components = URLComponents(string: registerUrl)!
components.queryItems = [
URLQueryItem(name: "api_key", value: apiKey),
URLQueryItem(name: "profile", value: jsonString)
]
Alamofire.request(components.url!, method: .post).responseJSON {
response in
if response.result.isSuccess {
let json: JSON = JSON(response.result.value!)
print(json)
}
}
Unfortunately, URLComponents will not percent encode + character although many (most?) web services require it to be (because, pursuant to the x-www-form-urlencoded spec, they replace + with space character). When I posted bug report on this, Apple's response was that this was by design, and that one should manually percent encode the + character:
var components = URLComponents(string: "https://www.wolframalpha.com/input/")!
components.queryItems = [
URLQueryItem(name: "i", value: "1+2")
]
components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
Obviously, if you were doing a standard application/json request, with the JSON in the body of the request, no such percent encoding is needed. But if you're going to include the JSON in the URL like this, then you will have to percent encode the + character yourself.
Alternatively, you can let Alamofire do this for you:
let parameters = [
"api_key": apiKey,
"profile": jsonString
]
Alamofire.request(url, method: .post, parameters: parameters).responseJSON { response in
...
}
This, admittedly puts the properly percent encoded value in the body of the POST request, not the URL as in your example, but generally in POST requests, that's what we want.

how to send JSON in post api using Alomofire SWIFT

I need to send JSON format in post api using alamofire in swift. Way data need to send is
{
"data": [{
"id": "1015683997",
"name": "Pawel"
}, {
"id": "108350039247",
"name": "Randeep"
}, {
"id": "115607797616",
"name": "Mohit"
}]
}
And way i am able to generate as of now is:
["data": {
data = (
{
id = 101583997;
name = "Pawel";
},
{
id = 108359247;
name = "Randeep";
},
{
id = 11567616;
name = "Mohit ";
}
);
}
]
Using the below mentioned way to generate json format.
for i in 0..<self.arrFriendsList.count
{
let dictFrndList:[String: AnyObject] = [
"id" : arrFriendsList[i].valueForKey("id")!,"name" : arrFriendsList[i].valueForKey("name")!
]
arrFrndList.addObject(dictFrndList)
}
Then,
let dictFBFrndList: [String: AnyObject] = [
"data":arrFrndList
]
Then,
let params: [String: AnyObject] = [
"access_token" : accessToken,
"data":dictFBFriends
]
So, please guide me. i have already spend more than a day on it. thanks in advance.
I second what Larme said, you should post "arrFrndList" at the params with key "data" but not dictFBFrndList.
Managed this way
let jsonData = try! NSJSONSerialization.dataWithJSONObject(arrFriendsList, options: NSJSONWritingOptions.PrettyPrinted)
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
print(jsonString)
let params: [String: AnyObject] = [
"access_token" : accessToken,
"data":jsonString
]
let options = NSJSONWritingOptions()
let data = try? NSJSONSerialization.dataWithJSONObject(parameters, options: options)
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string:"http:/myurl.com")
if let str = NSString(data: data!, encoding: NSUTF8StringEncoding) as? String {
print(str)
}
mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
mutableURLRequest.setValue("your_access_token", forHTTPHeaderField: "Authorization")
mutableURLRequest.HTTPBody = data
mutableURLRequest.HTTPMethod = "POST"
Alamofire.request(mutableURLRequest).responseJSON(){
json in
if let value = json.result.value {
let _json = JSON(value)
if (!_json.isEmpty){
print(_json)
}
}
}
you can check how to seen your JSON array this code. Look at 5th cell code. This code will write your json array for you in output screen and you can coppy from there and paste in here then you will see how to send data.
Maybe this way can help you .

Working with Neo4j Rest API in Swift

i am quite new to iOS and Swift and now i want to use Neo4j, a Graph Database for persistent saving of my data.
I know there's a Lib named Theo for connecting to the Graph Database, but i want to use the REST API. Now i am not sure how to handle the HTTP-Request in order to get data from Database to my iOS-App written in Swift?
Anyone has some helpful clues for my?
Thanks hannes
The Theo library that you mention is a wrapper around the Neo4j REST API. The benefit of using such a library is that it takes care of things like JSON serialization, error handling, adding the correct headers to HTTP requests, etc.
You can use Cypher with the transactional Cypher REST API endpoint using Swift like this (Note: this uses the Alamofire library for handling the HTTP request.):
import Alamofire
let cypherStatement = "CREATE (:Person {name: 'Bob'})-[:LIKES]->(pizza:Food {type: 'Pizza'})<-[:LIKES]-(:Person {name: 'William'}) WITH pizza MATCH (p:Person)-[:LIKES]->(pizz) RETURN p.name AS name"
let endpoint = "http://localhost:7474/db/data/transaction/commit"
let requestBody = [
"statements": [
[
"statement": cypherStatement
]
]
]
Alamofire.request(.POST, endpoint, parameters: requestBody, encoding: .JSON)
.responseJSON { response in
debugPrint(response)
}
Which logs:
[Request]: <NSMutableURLRequest: 0x7fafcb637320> { URL: http://localhost:7474/db/data/transaction/commit }
[Response]: <NSHTTPURLResponse: 0x7fafcb81d480> { URL: http://localhost:7474/db/data/transaction/commit } { status code: 200, headers {
"Access-Control-Allow-Origin" = "*";
"Content-Length" = 91;
"Content-Type" = "application/json";
Date = "Fri, 18 Dec 2015 19:29:41 GMT";
Server = "Jetty(9.2.z-SNAPSHOT)";
} }
[Data]: 91 bytes
[Result]: SUCCESS: {
errors = (
);
results = (
{
columns = (
name
);
data = (
{
row = (
Bob
);
},
{
row = (
William
);
}
);
}
);
}
Edit
Making the same request without using Alamofire would look like this:
let cypherStatement = "CREATE (:Person {name: 'Bob'})-[:LIKES]->(pizza:Food {type: 'Pizza'})<-[:LIKES]-(:Person {name: 'William'}) WITH pizza MATCH (p:Person)-[:LIKES]->(pizz) RETURN p.name AS name"
let endpoint = "http://localhost:7474/db/data/transaction/commit"
let requestBody = [
"statements": [
[
"statement": cypherStatement
]
]
]
guard let url = NSURL(string: endpoint) else {
print("Error")
return true
}
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("application/json",forHTTPHeaderField: "Accept")
do{
let jsonData = try NSJSONSerialization.dataWithJSONObject(requestBody, options: .PrettyPrinted)
request.HTTPBody = jsonData
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)
let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) in
let result: NSDictionary
do {
result = try NSJSONSerialization.JSONObjectWithData(data!,
options: []) as! NSDictionary
} catch {
print("error trying to convert data to JSON")
return
}
print("\(result)")
})
task.resume()
} catch let error as NSError {
print("JSON serialization error")
return true
}

Swift Alamofire upload image in variable for rails API

So here is my problem, I must upload an image in my swift application to a server that use rails. I got almost everything set up, except that the rails api must receive the file data in a variable document[:file]
here is the function I use to encode my image with alamofire:
static func getDocumentCreateUploadData(parameters: [String : AnyObject], imageData: NSData) -> (uploadData:NSMutableData, contentType:String) {
let boundaryConstant = "NET-POST-boundary-\(arc4random())-\(arc4random())";
let contentType = "multipart/form-data;boundary="+boundaryConstant
let uploadData = NSMutableData()
// add image
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(imageData)
// add parameters
for (key, value) in parameters {
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return (uploadData, contentType)
}
And then I call my api with
var imageParameters = [
"documents": [
"documentable_type": "Profile",
"documentable_id": user.profile.id!
]
]
let data = Router.getDocumentCreateUploadData(imageParameters, imageData: imageData)
let urlRequest = Router.CreateDocument(contentType: data.contentType)
Alamofire.upload(urlRequest, data.uploadData).validate().responseSwiftyJSON({ (request, response, json, error) in
if error != nil {
...
What I would like to know is how can I encode the image so that it respect the api specification.
{
"documents" : {
"file": the_file,
"documentable_type": the_documentable_type,
"documentable_id": the_documentable_id
}
}
Is there a way to achieve this?
Thank in advance.
I simply misundertood the api, I didn't needed the root document in my upload call
All I needed to do was remove the document root but here is the way I did it :
let imageParameters = [
"documentable_type": "Comment",
"organization_id": organizationId,
"member_id": memberId,
"user_id": user.id
]
let uuid = NSUUID().UUIDString
composeBarView.enabled = false
ProgressHUDManager.uploadingStatus()
Alamofire.upload(
Router.CreateDocument,
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data: imageData!, name: "file", fileName: "\(uuid).jpg", mimeType: "image/jpeg")
for (key, value) in imageParameters {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
},
encodingCompletion: { encodingResult in
// Handle result
}
)
The API Evolved so the code is new but I hope it can help