4

I'm trying to send a nested Json as body in one of the http post request from the flutter app I had been working on.

{
      "user" : {
        "UserName": "username",
        "password":"password",
        "Name": "name",
        "Email": "email"
      }
}

I tried many methods that were available online to do it, but every time I'm getting a 500 error. Below is a class to convert it into Json.

class SignupJson {
  String username;
  String email;
  String name;
  String password;

  SignupJson(this.email, this.name, this.password, this.username);

  Map toJson() =>{"user":{
    'UserName': username,
    'Name': name,
    'password': password,
    'Email': email
  }};

}

And pass on it to this for a post request. (I've put an arbitrary url link)

Future<int> attemptSignup ({String username, String password, String name, String email}) async {



    SignupJson data = SignupJson(username: username, password: password, name: name, email: email);
    var url = 'url';

    String body = jsonEncode(json);

    var res = await http.post(url,
    body: body);
    return res.statusCode;

  }

6 Answers 6

2

Add header like this:

Map<String, String> headers = {HttpHeaders.contentTypeHeader: "application/json"};

then in post request:

var res = await http.post(url, headers: headers, body: body);
Sign up to request clarification or add additional context in comments.

1 Comment

Hi! Actually the backend doesn't expect a header in this post request. Would it be still advisable?
0

Define map as <String, dynamic> e.g. :

Map<String, dynamic> data = {
"User": {
          "UserName":"username",
          "Password":"password"
    }
};

and add the following to the headers :

HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
request.headers.set('Accept', 'application/json');
request.headers.set('Content-type', 'application/json');
request.add(utf8.encode(json.encode(data)));
HttpClientResponse response = await request.close();
String reply = await utf8.decoder.bind(response).join();
httpClient.close();

3 Comments

Even if the backend doesn't expect headers with this request? In my logic flow, this request should output me the statusCode (Which if is ==200, gets people to next screen) . So where to get that status code here. And I'm a little confused with reply
You are sending JSON to the back-end, so Content-type must be set. response has an attribute named statusCode where you can check if it's 200 or not. So, you can check like if (response.statusCode == 200)
Is there a way I can connect to you? Your profile said you're accepting client
0

I have been stuck in this issue for last 2days. Below is the way how I overcome from my problem

Future<int> attemptSignup ({String username, String password, String name, String email}) async {


SignupJson data = SignupJson(username: username, password: password, name: name, email: email);
var url = 'url';

String body = jsonEncode(data);     

//here jsonEncode(data) return String bt in http body you are passing Map value

//So you have to convert String to Map
Map bodyMap = jsonDecode(body);         

// your nested json data
var bodyData = {       // where var store <String, dynamic> data as your demand
      "user" : bodyMap  
};


var res = await http.post(url,
body: bodyData,
headers: {"Content-Type": "application/json",},
);

return res.statusCode;

}

make sure to add header in http

1 Comment

@Siddharth Singh plz check this & let me know is it working for you :)
0

I code according to this json:

{
"user": {
    "UserName": "username",
    "password": "password",
    "Name": "name",
    "Email": "email"
  }
 }

Your Post Api call be like:

 Future<User> postUser(String username, String password, String name, String 
 email) async {

 Paste your api url here
 String url = '';
   final response = await http.post(apiUrl, headers: {
   // Enter your headers parameter if needed
   //  E.g: 
   'Authorization' : 'xyz',
   'Content-Type' : 'application/json'
 },
 body: jsonEncode(<String, String>{
   'UserName' : username,
   'password' : password,
   'Name' : name,
   'Email' : email
  }));

 if (response.statusCode == 200) {
    var data = jsonDecode(response.body.toString());
    print(data);
    return User.fromJson(jsonDecode(response.body));
  } else {
   throw Exception('Failed to post user.');
  }
}

Your model be like:

  class User {
     User? user;

     User({this.user});

     User.fromJson(Map<String, dynamic> json) {
       user = json['user'] != null ? new User.fromJson(json['user']) : null;
     }

    Map<String, dynamic> toJson() {
      final Map<String, dynamic> data = new Map<String, dynamic>();
      if (this.user != null) {
        data['user'] = this.user!.toJson();
      }
      return data;
     }
   }

  class User {
    String? userName;
    String? password;
    String? name;
    String? email;

      User({this.userName, this.password, this.name, this.email});

      User.fromJson(Map<String, dynamic> json) {
       userName = json['UserName'];
       password = json['password'];
       name = json['Name'];
       email = json['Email'];
     }

    Map<String, dynamic> toJson() {
       final Map<String, dynamic> data = new Map<String, dynamic>();
        data['UserName'] = this.userName;
        data['password'] = this.password;
        data['Name'] = this.name;
       data['Email'] = this.email;
      return data;
     }
    }

Comments

0

Since this is as yet unanswered, I'll take a stab. I've spent the same time as others troubleshooting against this issue and it's very frustrating.

What I learned is that the point of the content-type header is that it changes how Client.post structures the body as is creates the request, in addition to informing the server what type of data to expect. In my case, I had it erroneously set to 'application/x-www-form-urlencoded' which was working for other routes that I was passing individual maps of single-level objects and classes to, but it was failing on anything that had a key which had an object attached.

If I tried to pass a map on the key, it earned:

Expected a value of type 'String', but got one of type 'IdentityMap<String, dynamic>'.

and when I set the header properly but passed a map instead of a json.encode'ed map, I got:

Bad state: Cannot set the body fields of a Request with content-type "application/json".

From the Dart documentation for the post function:

Sends an HTTP POST request with the given headers and body to the given URL.

body sets the body of the request. It can be a String, a List or a Map<String, String>. If it's a String, it's encoded using encoding and used as the body of the request. The content-type of the request will default to "text/plain".

If body is a List, it's used as a list of bytes for the body of the request.

If body is a Map, it's encoded as form fields using encoding. The content-type of the request will be set to "application/x-www-form-urlencoded"; this cannot be overridden.

So we can see that if the specific header for content-type is missing OR if the content-type is set to application/json AND a map is passed to the body, the map will cause the post function to override the content-type header and set the header to urlencoded.

So even if the server is not expecting the content-type header, so to speak, it is expecting JSON-encoded data, and the only way to achieve that is to both:

  • Set the content-type header to application/json AND
  • Pass a properly json-encoded map (NOT a plain map) as the body parameter using jsonEncode( map ) or json.encode( map ) which are the same thing.

Comments

0

What worked for me is you have to set the Content-Type: application/json and also encode the request body using jsonEncode();

 final Map<String, String> requestHeaders = {
    "Authorization": "Bearer $token",
    "Accept": "application/json",
    "Content-Type": "application/json"
  };

  final reqBody = {
    "action": "Wallet.GetWalletConversionSummary",
    "data": {
      "source_currency": data["source_currency"],
      "destination_currency": data["destination_currency"],
      "amount": data["amount"]
    },
  };

  final response = await requestTypeCallMap[data["request_type"]]!(uri,
      headers: requestHeaders, body: jsonEncode(reqBody));
  print(jsonDecode(response.body));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.