Akshay
Akshay

Reputation: 179

Post method nsdictionary to json object iOS objective c

I am trying to send an array of dictionaries to server and before that I am converting to json format

NOTE:- the server is working well my friend in android is getting the response and data for successful post method

below is my code of post method:-

NSError *error;
NSMutableDictionary *tvarns = [[NSMutableDictionary alloc] init];
tvarns[@"order_cart"]=_order_cart;

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tvarns
                                                   options:NSJSONWritingPrettyPrinted error:&error];
NSLog(@"%@",jsonData);
NSString* order_cart;

order_cart = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"%@",order_cart);

NSString *post = [NSString stringWithFormat:@"%@",order_cart];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
//  Next up, we read the postData's length, so we can pass it along in the request.
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
// Now that we have what we'd like to post, we can create an NSMutableURLRequest, and include our postData
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"http://test.kre8tives.com/barebon/add_cartapi.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSLog(@"the data Details is %@", post);
//   And finally, we can send our request, and read the reply by creating a new NSURLSession:
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; // this is json string
    NSLog(@"Reply = %@", requestReply);
    //   NSError *error;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; // you need to convert to dictionary object
    NSLog(@"requestReply: %@", jsonDict);

}] resume];

[self presentViewController:alertController animated:YES completion:nil];
}

The value which the server wants is

{"order_cart":[{"customer_id":"114","item_id":14,"_id":"591d3822f55e2270202d8ff1","item_name":"Bira White","item_quantity":"2","price":"180.0","qr_code":"table21","phone":"7008841769","customer_name":"Samanthaa"},{"customer_id":"114","item_id":15,"_id":"591d3822f55e2270202d8ff0","item_name":"Bira Blonde","item_quantity":"2","price":"200.0","qr_code":"table21","phone":"7008841769","customer_name":"Samanthaa"}]}

My nslog is

2017-06-28 16:16:41.334 Barebones[3139:211622] the data Details is {
"order_cart" : [
{
  "phone" : "9047038606",
  "item_quantity" : "7",
  "qr_code" : "table21",
  "item_name" : "Bottled Water",
  "price" : "175",
  "customer_id" : "116",
  "customer_name" : "Akshay"
},
{
  "phone" : "9047038606",
  "item_quantity" : "2",
  "qr_code" : "table21",
  "item_name" : "Fresh Lime Soda(Sweet, Salt, Plain)",
  "price" : "158",
  "customer_id" : "116",
  "customer_name" : "Akshay"
},
{
  "phone" : "9047038606",
  "item_quantity" : "2",
  "qr_code" : "table21",
  "item_name" : "Bottled Water",
  "price" : "50",
  "customer_id" : "116",
  "customer_name" : "Akshay"
},
{
  "phone" : "9047038606",
  "item_quantity" : "2",
  "_id" : "591d3822f55e2270202d8ff0",
  "item_name" : "Bira Blonde",
  "price" : "86",
  "qr_code" : "table21",
  "customer_id" : "116",
  "item_id" : "3971",
  "customer_name" : "Akshay"
},
{
  "phone" : "9047038606",
  "item_quantity" : "1",
  "qr_code" : "table21",
  "item_name" : "Bottled Water",
  "price" : "25",
  "customer_id" : "116",
  "customer_name" : "Akshay"
   }
 ]
}
 2017-06-28 16:16:41.485 Barebones[3139:211669] Reply =   {"order_id":3961,"success":1}
<script type='text/javascript'    src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'>.      </script>
<script>
var data_array='{"source":{"name":"Kre8Tives","id":"SJQ6kyA1","order_id":"3961"},"customer":{"firstname":"","mobile":""},"tabType":"table","tabId":"591d3790498782970be66302","tableNumber":"1","items":null}';
alert(data_array);
 var settings = {
'async': true,
'crossDomain': true,
'url': 'http://posistapi.com/api/v1/table_order/push?customer_key=8c982f5e9ef091e9d5c8fb142311b49a68049b102de5e0987ebce29755c454227fbc7573c7da4199f126524a3ac7a39a&tabtype=table',
'method': 'POST',
'headers': {
'postman-token': 'e200ae19-d083-a98a-6db3-53fc2f8bd73f',
'cache-control': 'no-cache',
'authorization': 'Basic [removed]',
'content-type': 'application/json'
},
'processData': false,
'data': data_array,
 'acceptUrl':'http://test.kre8tives.com/barebon/order_confirm.php',
 'rejectUrl':'http://test.kre8tives.com/barebon/order_confirm.php',
 'billPrintUrl':'http://test.kre8tives.com/barebon/order_confirm.php'

}

$.ajax(settings).done(function (response) {
 console.log(response);
});
</script>
2017-06-28 16:16:41.486 Barebones[3139:211669] requestReply: (null)

I have converted to desired son format but still I am getting no reply from server

Even if I send return the data what I send from server I get null!!why is that ???thanks in advance !!:)

This is my PHP code

<?php
include('order-function.php');
if($_SERVER["REQUEST_METHOD"] == "POST") 
{

  $order_cart=$_POST['order_cart'];

  $items=json_decode($order_cart,true);

include('dbconfig.php');
$response = array();
try
    {
        $total_item_price=0;

        foreach ($items['order_cart'] as $item) {   //['order_cart']

        $customer_id=$item['customer_id'];
        $customer_name=$item['customer_name'];
        $phone=$item['phone'];
    $_id=$item['_id'];
        $item_name=$item['item_name'];
        $item_quantity=$item['item_quantity'];
        $price=$item['price'];
        $qr_code=$item['qr_code'];

  $products[]=array(
      "_id"=>"$_id",
      "item_name"=> $item_name,
      "item_price"=> $price,
            "item_quantity"=> $item_quantity

    );          

    $price_new+=$price;


       $item_push[]=array(
      "id"=>"$_id",
      "rate"=> $price,
            "quantity"=> $item_quantity

    );
      }


      $product_details=json_encode($products);
    $add_to_cart = "INSERT INTO order_cart (customer_id,product_details,order_amount,qr_code) VALUES ('$customer_id','$product_details','$price_new','$qr_code')";
      $result = mysqli_query($conn,$add_to_cart);
      $order_id=mysqli_insert_id($conn);

        if ($result) {

    $data['source']=array("name"=>"Kre8Tives",
                            "id"=>"SJQ6kyA1",
                  "order_id"=>"$order_id"
                );
    $data['customer']=array(
                        "firstname"=>"$customer_name",
                   "mobile"=>"$phone"
                );
     $data['tabType']= "table";
       $data['tabId']= "591d3790498782970be66302";
       $data['tableNumber']= "1";

       //items
       $data_one=json_encode($item_push,JSON_NUMERIC_CHECK);
       $data_new=json_decode($data_one);
       $data['items']=$data_new;

       $data_item=json_encode($data);


  $response["order_id"] = $order_id;
  $response["success"] = 1;

     // print_r(json_encode($data));die;


} else {
            $response["success"] = 0;
        }







 echo json_encode($response);
 push_order($data_item);

    }
catch(Exception $e)
    {
        $response["success"] = 0;
        $response["message"] = "error occured";
    }
}
?>

Upvotes: 2

Views: 1883

Answers (5)

Rob
Rob

Reputation: 437582

Frankly, looking at your NSLog results, it looks like the server code is erroneously returning some extra HTML (starting at the <script> line) after the JSON result. Looking at the body of the $response, it's reporting success, but it looks like some extra text is included in the response, either as a result of push_order, or some HTML after after the %>, or some web service error that is inserting some extra HTML.

Focusing on your client request code, it should set the Content-Type and Accept headers, though that’s not critical. But well designed requests should do that. The key issue is that the PHP should be outputting nothing else before or after the outputting of the JSON.

For what it's worth, if your web service was expecting a true JSON request, I would suggest a series of simplifications to your client code (in addition to setting those two additional headers). For example, just send the output of NSJSONSerialization as the httpBody; don't take that NSData, convert it to a NSString and then convert it back to a NSData. Just send jsonData as httpBody:

NSDictionary *tvarns = @{@"order_cart": _order_cart};

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tvarns
                                                   options:0
                                                     error:&error];

// if you want to see the JSON, you can do this, but this is not needed
//
// NSString *order_cart = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// NSLog(@"%@",order_cart);

// none of this stuff is needed; at worst, it can introduce encoding problems; at best, it's inefficient to do all that stuff
//
// NSString *post = [NSString stringWithFormat:@"%@",order_cart];
// NSLog(@"the data Details is %@", post);
// NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
// //  Next up, we read the postData's length, so we can pass it along in the request.
// NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

// Now that we have what we'd like to post, we can create an NSMutableURLRequest, and include our jsonData

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

[request setURL:[NSURL URLWithString:@"http://test.kre8tives.com/barebon/add_cartapi.php"]];
[request setHTTPMethod:@"POST"];

// you don't need this, because NSURLSession sets the length for you
//
// [request setValue:postLength forHTTPHeaderField:@"Content-Length"];

// use the original jsonData here

[request setHTTPBody:jsonData];

// you should, if you're a good web-service citizen, set the header; it's not always needed, but it's advisable

// tell the server that you're sending JSON request

[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

// tell the server that you're expecting JSON response

[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];

// Unless you need a new session for some reason, it's better to use the shared session

NSURLSession *session = [NSURLSession sharedSession];

[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (error) {
        NSLog(@"error: %@", error);
    }

    if (!data) {
        return;
    }

    NSError *parseError;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; // you need to convert to dictionary object
    if (jsonDict) {
        NSLog(@"requestReply: %@", jsonDict);
    } else {
        NSLog(@"parseError: %@", parseError);
        NSLog(@"response: %@", response); // when you have failure, it's sometimes useful to see what this says
        NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; // this is json string
        NSLog(@"requestReply: %@", requestReply);
    }
}] resume];

Again, having suggested these simplifications, I really suspect that there's a bug in the server code, including all that junk after the <script>.... I bet your Android code is ignoring all of this erroneous data at the end of the response, whereas NSJSONSerialization is correctly pointing out that the response is not, technically, well-formed JSON. (By the way, my code above will correctly log the JSON error.)


Looking at your PHP code that you've added to your revised question, it's grabbing $order_cart=$_POST['order_cart'];, which means that your web service is expecting a x-www-form-urlencoded request. The PHP code then proceeds to define $items as json_decode($order_cart,true) and then iterate with foreach through $items['order_cart']. That means that the web service is expecting x-www-form-urlencoded request whose value associated with order_cart key is, itself, a JSON dictionary keyed by order_cart (again), i.e., the request body will look like order_cart={"order_cart":[...]}.

That's not a very elegant design, but if you're stuck with that, you're going to have to create x-www-form-urlencoded request whose key is order_cart and whose value is a percent-encoded representation of a JSON dictionary of the form {"content-type":[...]}.

NSDictionary *tvarns = @{@"order_cart": _order_cart};

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tvarns
                                                   options:0
                                                     error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *bodyString = [NSString stringWithFormat:@"order_cart=%@", [jsonString stringByAddingPercentEncodingQueryValue]];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://test.kre8tives.com/barebon/add_cartapi.php"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];

// Unless you need a new session for some reason, it's better to use the shared session

NSURLSession *session = [NSURLSession sharedSession];

[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (error) {
        NSLog(@"error: %@", error);
    }

    if (!data) {
        return;
    }

    NSError *parseError;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; // you need to convert to dictionary object
    if (jsonDict) {
        NSLog(@"requestReply: %@", jsonDict);
    } else {
        NSLog(@"parseError: %@", parseError);
        NSLog(@"response: %@", response); // when you have failure, it's sometimes useful to see what this says
        NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; // this is json string
        NSLog(@"requestReply: %@", requestReply);
    }
}] resume];

Where:

@interface NSCharacterSet (URLQueryValue)

/**
 Character set of characters allowed within value (or a key) in a application/x-www-form-urlencode key/value pair.

 @return NSCharacterSet of allowed characters.
 */
+ (NSCharacterSet *) URLQueryValueAllowedCharacterSet;

@end

@implementation NSCharacterSet (URLQueryValue)

+ (NSCharacterSet *) URLQueryValueAllowedCharacterSet {
    static NSString * const generalDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
    static NSString * const subDelimitersToEncode = @"!$&'()*+,;=";

    NSString * const characterToEncode = [generalDelimitersToEncode stringByAppendingString:subDelimitersToEncode];

    NSMutableCharacterSet *cs = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [cs removeCharactersInString:characterToEncode];
    return cs;
}

@end

And

@interface NSString (URLQueryValue)
/**
 String percent encoding for key or value in key/value pair within an application/x-www-form-urlencoded request.

 @return Percent encoded string.
 */
- (NSString *)stringByAddingPercentEncodingQueryValue;
@end

@implementation NSString (URLQueryValue)
- (NSString *)stringByAddingPercentEncodingQueryValue {
    return [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
}
@end

Frankly, I'd suggest changing the web service to process a true JSON request, not JSON within a x-www-form-urlencoded request. If you did that, the client code would look more like my original answer above. But for your existing web service code, you'd create something like my second code sample.

Upvotes: 1

Patrick Bodet
Patrick Bodet

Reputation: 681

NSDictionary *dict = @{@"order_cart": _order_cart};
NSLog(@"dict = %@", dict);

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];

// For debug
NSString *postString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"postString = %@", postString);
//

NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[jsonData length]];

NSURL *url = [NSURL URLWithString:@"http://test.kre8tives.com/barebon/add_cartapi.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:jsonData];

NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    if (!error) {
        id jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
        NSLog(@"jsonDict = %@", jsonDict);
        if (!error) {

        }
        else {

        }
    }
    else {

    }
}];

[task resume];

Upvotes: 1

Ravi Panchal
Ravi Panchal

Reputation: 1355

Your array is correct just convert to json string

Here is func for that

public func jsonString(prettify: Bool = false) -> String? {
        guard JSONSerialization.isValidJSONObject(self) else {
            return nil
        }

Use it this way

 self.arrOrderCart.jsonString()

Upvotes: 0

CodeChanger
CodeChanger

Reputation: 8351

You have to pass directly NSData to HttpBody like below :

NSDictionary *headers = @{ @"content-type": @"application/json",
                           @"cache-control": @"no-cache"
                         };

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:tvarns
                                                   options:NSJSONWritingPrettyPrinted error:&error];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://test.kre8tives.com/barebon/add_cartapi.php"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

Hope this will helps to get your data request success!

Upvotes: 0

Neha Gupta
Neha Gupta

Reputation: 539

Try below code

NSMutableDictionary *parametersDictionary = [[NSMutableDictionary alloc]init];
[parametersDictionary setValue:@"114" forKey:@"customer_id"];
[parametersDictionary setValue:@"14" forKey:@"item_id"];
[parametersDictionary setValue:@"591d3822f55e2270202d8ff1" forKey:@"_id"];
[parametersDictionary setValue:@"Bira White" forKey:@"item_name"];
[parametersDictionary setValue:@"2" forKey:@"item_quantity"];
[parametersDictionary setValue:@"180.0" forKey:@"price"];
[parametersDictionary setValue:@"table21" forKey:@"qr_code"];
[parametersDictionary setValue:@"7008841769" forKey:@"phone"];
[parametersDictionary setValue:@"Samanthaa" forKey:@"customer_name"];

NSMutableDictionary *requestParametersDic=[[NSMutableDictionary alloc] initWithObjectsAndKeys:parametersDictionary,@"order_cart", nil];

NSData * postData=[NSJSONSerialization dataWithJSONObject:requestParametersDic options:NSJSONWritingPrettyPrinted error:nil];


NSString *postLength = [NSString stringWithFormat:@"%lu",(unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@",KWebservicesBaseURL,kiPestConfirmOrder]]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:nil delegateQueue:nil];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
    NSString *responseString=[[NSString alloc]init];

    if(data!=nil && httpResponse.statusCode==200)
    {
        responseString=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        // NSLog(@"i deliver add order reponse str %@",responseString);
    }
    else
    {

    }
}];

[postDataTask resume];

Upvotes: 0

Related Questions