Flutter: Send JSON body for Http GET request - json

I need to make a GET request to an API from my Flutter app which requires request body as JSON (raw).
I tested the API with JSON request body in Postman and it seems to be working fine.
Now on my Flutter application I am trying to do the same thing:
_fetchDoctorAvailability() async {
var params = {
"doctor_id": "DOC000506",
"date_range": "25/03/2019-25/03/2019" ,
"clinic_id":"LAD000404"
};
Uri uri = Uri.parse("http://theapiiamcalling:8000");
uri.replace(queryParameters: params);
var response = await http.get(uri, headers: {
"Authorization": Constants.APPOINTMENT_TEST_AUTHORIZATION_KEY,
HttpHeaders.contentTypeHeader: "application/json",
"callMethod" : "DOCTOR_AVAILABILITY"
});
print('---- status code: ${response.statusCode}');
var jsonData = json.decode(response.body);
print('---- slot: ${jsonData}');
}
However the API gives me an error saying
{message: Missing input json., status: false}
How do I send a raw (or rather JSON) request body for Http GET request in Flutter?

GET
GET requests are not intended for sending data to the server (but see this). That's why the http.dart get method doesn't have a body parameter. However, when you want to specify what you are getting from the server, sometimes you need to include query parameters, which is a form of data. The query parameters are key-value pairs, so you can include them as a map like this:
final queryParameters = {
'name': 'Bob',
'age': '87',
};
final uri = Uri.http('www.example.com', '/path', queryParameters);
final headers = {HttpHeaders.contentTypeHeader: 'application/json'};
final response = await http.get(uri, headers: headers);
POST
Unlike GET requests, POST requests are intended for sending data in the body. You can do it like this:
final body = {
'name': 'Bob',
'age': '87',
};
final jsonString = json.encode(body);
final uri = Uri.http('www.example.com', '/path');
final headers = {HttpHeaders.contentTypeHeader: 'application/json'};
final response = await http.post(uri, headers: headers, body: jsonString);
Note that the parameters were a Map on the Dart side. Then they were converted to a JSON string by the json.encode() function from the dart:convert library. That string is the POST body.
So if the server is asking you to pass it data in a GET request body, check again. While it is possible to design a server in this way, it isn't standard.

uri.replace... returns a new Uri, so you have to assign it into a new variable or use directly into the get function.
final newURI = uri.replace(queryParameters: params);
var response = await http.get(newURI, headers: {
"Authorization": Constants.APPOINTMENT_TEST_AUTHORIZATION_KEY,
HttpHeaders.contentTypeHeader: "application/json",
"callMethod" : "DOCTOR_AVAILABILITY"
});
using post:
var params = {
"doctor_id": "DOC000506",
"date_range": "25/03/2019-25/03/2019" ,
"clinic_id":"LAD000404"
};
var response = await http.post("http://theapiiamcalling:8000",
body: json.encode(params)
,headers: {
"Authorization": Constants.APPOINTMENT_TEST_AUTHORIZATION_KEY,
HttpHeaders.contentTypeHeader: "application/json",
"callMethod" : "DOCTOR_AVAILABILITY"
});

You can use Request class as following:
var request = http.Request(
'GET',
Uri.parse("http://theapiiamcalling:8000"),
)..headers.addAll({
"Authorization": Constants.APPOINTMENT_TEST_AUTHORIZATION_KEY,
HttpHeaders.contentTypeHeader: "application/json",
"callMethod": "DOCTOR_AVAILABILITY",
});
var params = {
"doctor_id": "DOC000506",
"date_range": "25/03/2019-25/03/2019",
"clinic_id": "LAD000404"
};
request.body = jsonEncode(params);
http.StreamedResponse response = await request.send();
print(response.statusCode);
print(await response.stream.bytesToString());
Also, note that Postman that can convert an API request into a code snippet in more than 15 languages. If you select Dart, you will find a similar code to above.

It may help someone those who used Getx for api integration . We can use request method for these kind of requirement.
Map<String, dynamic> requestBody = { 'id' : 1};
Response<Map<String, dynamic>> response =
await request(url, 'get', body: requestBody);

if you want to send complex/nested data through a GET request like the sample below, you can use a simple class i created on github
https://github.com/opatajoshua/SimplifiedUri
final params = {
'name': 'John',
'columns': ['firstName', 'lastName'],
'ageRange': {
'from': 12,
'to': 60,
},
'someInnerArray': [1,2,3,5]
};
final Uri uri = SimplifiedUri.uri('http://api.mysite.com/users', params);
final headers = {HttpHeaders.contentTypeHeader: 'application/json'};
final response = await http.get(uri, headers: headers);
output
http://api.mysite.com/users?name=John&columns%5B%5D=firstName&columns%5B%5D=lastName&ageRange%5Bfrom%5D=12&ageRange%5Bto%5D=60&someInnerArray%5B%5D=1&someInnerArray%5B%5D=2&someInnerArray%5B%5D=3&someInnerArray%5B%5D=5

Related

How to get title/item from response.body (HTTP - JSON)

I want to pull certain headers and items under the headers as string data from the JSON.
Map dataSignUpEmployeer = {
'corporationName': employeer.getCorporationName(),
'webSiteName': employeer.getWebSiteName(),
'email': employeer.getEmail(),
'password': employeer.getPassword(),
};
String bodySignUpEmployeer = json.encode(dataSignUpEmployeer);
postDataSignUpEmployeer() async {
final response = await http.post(
Uri.parse(urlSignUp),
headers: {"Content-Type": "application/json"},
body: bodySignUpEmployeer,
);
return response.body;
}
response.body return JSON
Eesponse.body's return:
Please help me in any way.
your code is working as well i see so i think you wrong in a part of your code for get the success: true from your response body so maybe you need to authorize your user in header of post method with Token. to get back success true and get all of each user data. any way we should see your api url.

Send multiple files in json body

I am new in flutter, trying to send multiple files in single request but failing miserably. I have attached the json body parameter screenshot also.
I have to send an array of multiple pdf files along with other parameters.
qualifications:{"qualifications": [{"id": "25", "qualification": "nurse", "grade": 11, "date": "2020-07-20", "proof": "file"}]}
nurse_id:26
This is what i did
List<Map> _jsonArray = new List();
Map<String, String> arrayBody = {
'id': '',
'qualification': 'nurse',
'grade': '13',
'date': _dateController.text,
};
List<http.MultipartFile> _mfiles = new List();
_jsonArray.add(arrayBody);
var body = json.encode({'qualifications':_jsonArray });
_mfiles.add( await http.MultipartFile.fromPath(
'proof',
_file
),
);
_mfiles.add( await http.MultipartFile.fromPath(
'qt_statement',
_qtStatement
),);
final Map<String, String> requestheaders = {
'Authorization': 'Bearer '+token_id,
};
var request = http.MultipartRequest('POST', Uri.parse(Urls.PERSONAL_DETAILS));
request.headers.addAll(requestheaders);
request.files.addAll(_mfiles);
request.fields[Constants.nurse_id] = nurse_id;
var res = await request.send();
var content = StringBuffer();
if(res.statusCode == 200){
res.stream.transform(utf8.decoder).listen((value) {
content.write(value);
},
onDone: (){
var data = json.decode(content.toString());
print(data);
});
}
The json i am sending looks like this
{"qualifications":[{"id":"","qualification":"nurse","grade":"13","date":"2020-07-31"}]}
Here 'proof' key is missing. Hence, getting 'Proof cannot be null' as response from server.
Struggling with this issue for more than 3 hours. Any suggestion or help will be highly appreciated
i assume your server expects the request to have a field called proof which contains the file data as part of the json post data. In this case, you can encode the file content (bytes) as base64 and set it inside your json data.
something like:
string proof = read_file_as_base64(filepath); //you need to read and encode the file content here.
Map<String, String> arrayBody = {
'id': '',
'qualification': 'nurse',
'grade': '13',
'date': _dateController.text,
'proof': proof
};

how to post json array on flutter

I have some problem to post json array with flutter.
When I hit api with postman using json it works. Screenshot postman:
Since I know on body just accept Map <String,String> CMIIW
so i turn body into like this
List<Map<String,String>> products = [
{
"product_id": "1",
"buy_quantity": "1",
"product_price": "1000",
"is_voucher": "0",
},
{
"product_id": "2",
"buy_quantity": "2",
"product_price": "2000",
"is_voucher": "0",
},
];
final String jsonProduct = json.encode(products);// here im trying to
Map<String,String> _body = {
"buyer_id": '',
"buyer_firstname": postCart.buyerFirstname,
"phone_number": postCart.phoneNumber,
"transaction_total_price": postCart.transactionTotalPrice.toString(),
"voucher_id": 0.toString(),
"voucher_code": 0.toString(),
"payment_id": postCart.paymentId.toString(),
"payment_name": postCart.paymentName,
"products" : jsonProduct
};
but i still got error,
thanks!
I'm assuming that you are using the http package.
This is an example of how to make an HTTP POST request with a json payload on the body:
Future<Lead> createLead(String clientName, String clientEmail, String clientPhone, String eventId) async {
// Create storage
final storage = new FlutterSecureStorage();
// Get API url from env
String url = (DotEnv().env['BASE_URL'] + "/leads/create");
String authToken = await storage.read(key: 'api-token');
// Create some request headers
Map<String, String> requestHeaders = {
'Content-type': 'application/json',
'Accept': 'application/json',
'X-Token': authToken
};
final response = await http.post(
url,
// enconde some JSON data on the request body
body: json.encode(
{
'event_id': eventId,
'name': clientName,
'phone': clientPhone,
'email': clientEmail
}
),
headers: requestHeaders
);
if (response.statusCode == 200) {
final leadsJson = json.decode(response.body);
Lead lead = Lead.fromJson(leadsJson);
return lead;
} else {
// If that response was not OK, throw an error.
// throw Exception('Failed to load post');
return null;
}
}
Hope it helps.
If you want to achieve the JSON in the screen shot you need to make several changes.
Notice that the list of products shows unquoted integers when converted to JSON, so these need to be kept as ints in your Dart class. (Note the preferred syntax, too.)
var products = <Map<String, int>>[
{
'product_id': 1,
'buy_quantity': 1,
'product_price': 1000,
'is_voucher': 0,
},
{
'product_id': 2,
'buy_quantity': 2,
'product_price': 2000,
'is_voucher': 0,
},
];
The type of _body needs to change because it now contains a list as well as strings. (Keep the rest the same - like the toStrings - as your screenshot shows that even the integers are quoted as strings.)
var _body = <String, dynamic>{
'buyer_id': '',
'buyer_firstname': postCart.buyerFirstname,
'phone_number': postCart.phoneNumber,
'transaction_total_price': postCart.transactionTotalPrice.toString(),
'voucher_id': 0.toString(),
'voucher_code': 0.toString(),
'payment_id': postCart.paymentId.toString(),
'payment_name': postCart.paymentName,
'products': products
};
Lastly json and (preferably) utf8 encode the resulting map, and pass that as the body parameter of your http.post.
var bytes = utf8.encode(json.encode(_body));
await http.post(url, body: bytes, headers: someHeaders);
One of your headers could be content-type: application/json;encoding=utf-8 to tell the server that you are sending UTF8 encoded JSON.

How To Make Post To A External API With Methods And Data By Dart

I Have A Web Service And Want To Post Data By Flutter Dart json In My WebService API Link
For REST API calls I prefer to use a library named Dio. Its way too easy to make GET, POST, PUT, DELETE etc calls using Dio.
For Example
import 'package:dio/dio.dart';
//Now like this
void _makeApiCall() async {
Dio dio = new Dio();
Response apiResponse = await dio.get('${YOUR URL}?id=$id'); //Where id is just a parameter in GET api call
print(apiResponse.data.toString());
}
And If you want to make a POST call and you need to send Form data with that do like this
void _makeApiCall() async {
Dio dio = new Dio();
FormData formData = FromData.from({
name : "name",
password: "your password",
}); // where name and password are api parameters
Response apiResponse = await dio.post('${YOUR URL}', data: formData);
print(apiResponse.data.toString());
}
Also you can map the received data into so called POJOs for better handling and usage.
If you want to know how to map the data into POJO (Objects), Just let me know.
you need to be more specif about the API and what you want to send. this is a simple example from the HTTP client library
import 'package:http/http.dart' as http;
var url = "http://example.com/whatsit/create";
http.post(url, body: {"name": "doodle", "color": "blue"})
.then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
});
http.read("http://example.com/foobar.txt").then(print);
Could you please provide more details on the API?
Imagine your API takes data like so, http://localhost:3000
You can make the request as follows
Future<String> create(String text) async {
HttpClient client = new HttpClient();
try {
HttpClientRequest req = await client.post('localhost', 3000, '/');
req.headers.contentType = new ContentType("application", "json", charset: "utf-8");
req.write('{"key":"value"}');
HttpClientResponse res = await req.close();
if (res.statusCode == HttpStatus.CREATED) return await res.transform(UTF8.decoder).join();
else throw('Http Error: ${res.statusCode}');
} catch (exception) {
throw(exception.toString());
}
}
OR
If you would like to post a Map (created from whatever json you have), you can use the http package. https://pub.dartlang.org/packages/http
import 'package:http/http.dart' as http;
String url = "http://example.com/whatsit/create";
http.post(url, body: {"name": "doodle", "color": "blue"})
.then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
});
I recommend using this packages dio package
doing post will be like this :
Future<List> postDataFromURL_list(String url, Map map) async {
// TODO: implement postDataFromURL_list
Response response;
Dio dio = new Dio();
FormData formData = new FormData.from(map);
response = await dio.post(url, data: formData);
}

Spring MVC Multipart Request with JSON

I want to post a file with some JSON data using Spring MVC. So I've developed a rest service as
#RequestMapping(value = "/servicegenerator/wsdl", method = RequestMethod.POST,consumes = { "multipart/mixed", "multipart/form-data" })
#ResponseBody
public String generateWSDLService(#RequestPart("meta-data") WSDLInfo wsdlInfo,#RequestPart("file") MultipartFile file) throws WSDLException, IOException,
JAXBException, ParserConfigurationException, SAXException, TransformerException {
return handleWSDL(wsdlInfo,file);
}
When I send a request from the rest client with
content-Type = multipart/form-data or multipart/mixed, I get the next exception:
org.springframework.web.multipart.support.MissingServletRequestPartException
Can anyone help me in solving this issue?
Can I use #RequestPart to send both Multipart and JSON to a server?
This is how I implemented Spring MVC Multipart Request with JSON Data.
Multipart Request with JSON Data (also called Mixed Multipart):
Based on RESTful service in Spring 4.0.2 Release, HTTP request with the first part as XML or JSON formatted data and the second part as a file can be achieved with #RequestPart. Below is the sample implementation.
Java Snippet:
Rest service in Controller will have mixed #RequestPart and MultipartFile to serve such Multipart + JSON request.
#RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,
consumes = {"multipart/form-data"})
#ResponseBody
public boolean executeSampleService(
#RequestPart("properties") #Valid ConnectionProperties properties,
#RequestPart("file") #Valid #NotNull #NotBlank MultipartFile file) {
return projectService.executeSampleService(properties, file);
}
Front End (JavaScript) Snippet:
Create a FormData object.
Append the file to the FormData object using one of the below steps.
If the file has been uploaded using an input element of type "file", then append it to the FormData object.
formData.append("file", document.forms[formName].file.files[0]);
Directly append the file to the FormData object.
formData.append("file", myFile, "myfile.txt"); OR formData.append("file", myBob, "myfile.txt");
Create a blob with the stringified JSON data and append it to the FormData object. This causes the Content-type of the second part in the multipart request to be "application/json" instead of the file type.
Send the request to the server.
Request Details:
Content-Type: undefined. This causes the browser to set the Content-Type to multipart/form-data and fill the boundary correctly. Manually setting Content-Type to multipart/form-data will fail to fill in the boundary parameter of the request.
Javascript Code:
formData = new FormData();
formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
Request Details:
method: "POST",
headers: {
"Content-Type": undefined
},
data: formData
Request Payload:
Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryEBoJzS3HQ4PgE1QB
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="file"; filename="myfile.txt"
Content-Type: application/txt
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="properties"; filename="blob"
Content-Type: application/json
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN--
This must work!
client (angular):
$scope.saveForm = function () {
var formData = new FormData();
var file = $scope.myFile;
var json = $scope.myJson;
formData.append("file", file);
formData.append("ad",JSON.stringify(json));//important: convert to JSON!
var req = {
url: '/upload',
method: 'POST',
headers: {'Content-Type': undefined},
data: formData,
transformRequest: function (data, headersGetterFunction) {
return data;
}
};
Backend-Spring Boot:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public #ResponseBody
Advertisement storeAd(#RequestPart("ad") String adString, #RequestPart("file") MultipartFile file) throws IOException {
Advertisement jsonAd = new ObjectMapper().readValue(adString, Advertisement.class);
//do whatever you want with your file and jsonAd
You can also use the next way a list List<MultipartFile> and #RequestPart("myObj") as parameters in your method inside a #RestController
#PostMapping()
#ResponseStatus(HttpStatus.CREATED)
public String create(#RequestPart("file") List<MultipartFile> files, #RequestPart("myObj") MyJsonDTOClass myObj) throws GeneralSecurityException, IOException {
// your code
}
and in the axios side with a bit of react:
const jsonStr = JSON.stringify(myJsonObj);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
formData.append("myObj",blob );
formData.append("file", this.state.fileForm); // check your control
let url = `your url`
let method = `post`
let headers =
{
'Accept': 'application/json',
'Content-Type': 'application/json'
};
}
axios({
method,
url,
data: formData,
headers
}).then(res => {
console.log(res);
console.log(res.data);
});
We've seen in our projects that a post request with JSON and files is creating a lot of confusion between the frontend and backend developers, leading to unnecessary wastage of time.
Here's a better approach: convert file bytes array to Base64 string and send it in the JSON.
public Class UserDTO {
private String firstName;
private String lastName;
private FileDTO profilePic;
}
public class FileDTO {
private String base64;
// just base64 string is enough. If you want, send additional details
private String name;
private String type;
private String lastModified;
}
#PostMapping("/user")
public String saveUser(#RequestBody UserDTO user) {
byte[] fileBytes = Base64Utils.decodeFromString(user.getProfilePic().getBase64());
....
}
JS code to convert file to base64 string:
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
const userDTO = {
firstName: "John",
lastName: "Wick",
profilePic: {
base64: reader.result,
name: file.name,
lastModified: file.lastModified,
type: file.type
}
}
// post userDTO
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
As documentation says:
Raised when the part of a "multipart/form-data" request identified by
its name cannot be found.
This may be because the request is not a multipart/form-data either
because the part is not present in the request, or because the web
application is not configured correctly for processing multipart
requests -- e.g. no MultipartResolver.
For Angular2+ users. Try to send JSON payload in a mixed part request as below.
formData.append("jsonPayload", new Blob([JSON.stringify(json)], {
type: "application/json"
}));
Given below complete function.
submit() {
const formData = new FormData();
formData.append('file', this.myForm.get('fileSource').value);
var json = {
"key":"value"
};
formData.append("jsonPayload", new Blob([JSON.stringify(json)], {
type: "application/json"
}));
this.http.post('http://localhost:8080/api/mixed-part-endpoint', formData)
.subscribe(res => {
console.log(res);
alert('Uploaded Successfully.');
})
}