JSON localized strings retuned from API are invalid - flutter

I have been trying to get a JSON response form API call which return a localised strings. Works well in Postman with same setup as http calls. but when make an API call from application it returns weird string - please check below.
I tried passing header for supporting language but does not work
JSON response in Postman - "text": "Número OMI-IMO",
JSON response through application - "text":"Número OMI-IMO"
http.Response response = await http.get(
login,
headers: {'Consumer-Key': consumerKey, 'Accept-Language': '*'},
);
I have also tried setting my device default language to respective localized language in this case Spanish, local strings used int he application works fine.
Tried binding the string "text": "Número OMI-IMO", from JSON file works well.
The response re not working only with API response strings, its same with other language like Frensh, Portuguese.
Been trying different solution but nothing work this problem exist on both Android and iOS.

Import this dart lib on the head of the file
import 'dart:convert' as convert
then you do
String jsonString = convert.utf8.decode(response.bodyBytes);
Now you will have a proper formatted and decoded JSON

Related

Flutter - Making a web request

I would like to know if there is a way to format special characters when parsing JSON requests from Flutter. I have tested a http request as such:
void curlRequest() async
{
String urlRequest = "http://my.web.url/webservice/rest/server.php?wstoken=my_token&moodlewsrestformat=json&wsfunction=core_user_create_users&users[0][username]=test_user_4&users[0][firstname]=John&users[0][lastname]=Doe&users[0][email]=john.doe#gmail.com&users[0][password]=Johns_Password";
http.post(urlRequest, headers: {'Content-type': 'application/json; charset=utf-8'}).then((response){
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
});
}
I get the following response:
http://my.web.url/webservice/rest/server.php?wstoken=my_token&moodlewsrestformat=json&wsfunction=core_user_create_users&users%5B0%5D%5Busername%5D=test_user_4&users%5B0%5D%5Bfirstname%5D=John&users%5B0%5D%5Blastname%5D=Doe&users%5B0%5D%5Bemail%5D=john.doe#gmail.com&users%5B0%5D%5Bpassword%5D=Johns_Password&i=1
The request was invalid due to special characters being used. How do I make a request so that the special characters are also handled properly?
In a http restful request, the http GET request must be url encoded, which means that most special characters must be encoded in a way understandable by a webserver.
As such, characters such as the plus sign (+) or the question mark (?) must be replaced by their URL encoded equivalents (%2b for the plus sign and %3F for a question mark for instance) and vice versa for decoding.
Several URL encoders can be found online such as http://www.url-encode-decode.com/
In Dart you can use Uri.encodeFull() to encode string and Uri.encodeComponent() to encode a string component
Similarly to decode you can use Uri.decodeFull() and others
read more about this here Uri class
Switching to a better web hosting service resolved my issue. I was using AeonFree, which was a free web hosting service and had limited access for obvious reasons.
I also switched from the http package to using the dio package.

POST image to web service with Flutter

I am currently using Flutter and Dart to try to send an image to a web service, after which I wait for a JSON response. The below links show the Postman request that I am trying to mimic.
An image of Postman with the headers required
An image of Postman with the body
I think the issue I am having is either not setting the headers of my request correctly, or not encoding the image correctly.
Currently I am getting a HTTP 400 error.
I have tried following these suggested solutions on StackOverflow but have been getting the HTTP 400 error.
Any help would be much appreciated!
Try this. I'd suggest creating yourself a plain Dart project, if you haven't already. This way you can test things without the need of the phone emulator, etc.
main() async {
http.MultipartRequest request =
new http.MultipartRequest('POST', Uri.parse(url));
request.headers['Prediction-Key'] = '3f4a......'; // todo - insert real value
request.files.add(
new http.MultipartFile.fromBytes(
'image',
bytes,
filename: 'somefile', // optional
contentType: new MediaType('image', 'jpeg'),
),
);
http.StreamedResponse r = await request.send();
print(r.statusCode);
}
If the file is on disk, not in memory, then use the fromPath named constructor instead. Experiment with different media types. I've used image/jpeg, but you could try application/octet-stream.
As an aside, in your first screenshot you show a content type, but Postman ignores this as the overall content type is overridden by multipart-form. Uncheck that row in Postman to prove this.
There was another question recently on SO, where the server was incorrectly expecting headers to be case sensitive. In postman, try again with lowercase prediction-key to prove that the server doesn't mind lowercase headers (which is what Dart uses).

Need to find the requests equivalent of openurl() from urllib2

I am currently trying to modify a script to use the requests library instead of the urllib2 library. I haven't really used it before and I am looking to do the equivalent of urlopen("http://www.example.org").read(), so I tried the requests.get("http://www.example.org").text function.
This works fine with normal everyday html, however when I fetch from this url (https://gtfsrt.api.translink.com.au/Feed/SEQ) it doesn't seem to work.
So I wrote the below code to print out the responses from the same url using both the requests and urllib2 libraries.
import urllib2
import requests
#urllib2 request
request = urllib2.Request("https://gtfsrt.api.translink.com.au/Feed/SEQ")
result = urllib2.urlopen(request)
#requests request
result2 = requests.get("https://gtfsrt.api.translink.com.au/Feed/SEQ")
print result2.encoding
#urllib2 write to text
open("Output.txt", 'w').close()
text_file = open("Output.txt", "w")
text_file.write(result.read())
text_file.close()
open("Output2.txt", 'w').close()
text_file = open("Output2.txt", "w")
text_file.write(result2.text)
text_file.close()
The openurl().read() works fine but the requests.get().text doesn't work for the given this url. I suspect it has something to do with encoding, but i don't know what. Any thoughts?
Note: The supplied url is a feed in the google protocol buffer format, once I receive the message i give the feed to a google library that interprets it.
Your issue is that you're making the requests module interpret binary content in a response as text.
A response from the requests library has two main way to access the body of the response:
Response.content - will return the response body as a bytestring
Response.text - will decode the response body as text and return unicode
Since protocol buffers are a binary format, you should use result2.content in your code instead of result2.text.
Response.content will return the body of the response as-is, in bytes. For binary content this is exactly what you want. For text content that contains non-ASCII characters this means the content must have been encoded by the server into a bytestring using a particular encoding that is indicated by either a HTTP header or a <meta charset="..." /> tag. In order to make sense of those bytes they therefore need to be decoded after receiving using that charset.
Response.text now is a convenience method that does exactly this for you. It assumes the response body is text, and looks at the response headers to find the encoding, and decodes it for you, returning unicode.
But if your response doesn't contain text, this is the wrong method to use. Binary content doesn't contain characters, because it's not text, so the whole concept of character encoding does not make any sense for binary content - it's only applicable to text composed of characters. (That's also why you're seeing response.encoding == None - it's just bytes, there is no character encoding involved).
See Response Content and Binary Response Content in the requests documentation for more details.

Play Framework Ning WS API encoding issue with HTML pages

I'm using Play Framework 2.3 and the WS API to download and parse HTML pages. For none-English pages (e.g Russian, Hebrew), I often get wrong encoding.
Here's an example:
def test = Action.async { request =>
WS.url("http://news.walla.co.il/item/2793388").get.map { response =>
Ok(response.body)
}
}
This returns the web page's HTML. English characters are received ok. The Hebrew letters appear as Gibberish. (Not just when rendering, at the internal String level). Like so:
<title>29 ×ר×××× ××פ××ת ×ש×××× ×× ×¤××, ××× ×©×××©× ×שר×××× - ×××××! ××ש×ת</title>
Other articles from the same web-site can appear ok.
using cURL with the same web-page returns perfectly fine which makes me believe the problem is within the WS API.
Any ideas?
Edit:
I found a solution in this SO question.
Parsing the response as ISO-8859-1 and then converting it to UTF-8 like-so:
Ok(new String(response.body.getBytes("ISO-8859-1") , response.header(CONTENT_ENCODING).getOrElse("UTF-8")))
display correctly. So I have a working solution, but why isn't this done internally?
Ok, here the solution I ended up using in production:
def responseBody = response.header(CONTENT_TYPE).filter(_.toLowerCase.contains("charset")).fold(new String(response.body.getBytes("ISO-8859-1") , "UTF-8"))(_ => response.body)
Explanation:
If the request returns a "Content-Type" header that also specifies a charset, simply return the response body sine the WS API will use it to decode correctly, otherwise, assume the response is ISO-8859-1 encoded and convert it to UTF-8

RestyGWT: does it support plain text?

I'm not able to receive plain text using RestyGWT. A very simple test service looks like this:
#GET
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
void test(MethodCallback<String> callback);
On the client side I always get:
Response was NOT a valid JSON document
Looking at the HTTP response I'm seeing that content type is set correctly:
Content-Type:text/plain
What's the problem? Why RestyGWT tries to parse this as JSON? Am I doing smth wrong?
If you will use TextCallback instead of MethodCallback<String> you won't get this error.
It will set Accept header automatically to text/plain, so you don't have to use #Produces adnotation in your async interface.
Well, RestyGWT is a Json library, AFAIK it is not made to handle plain text, or XML, or anything else. "foo" isn't a valid Json data, should be ["foo"] or {"stuff": "foo"}.
Indeed, in our Rest API, we tried to send pure text (an id), but we finally made a simple object wrapping the id.