Serializing Special Character in Flutter [duplicate] - flutter

I am building a mobile app with Flutter.
I need to fetch a json file from server which includes Japanese text. A part of the returned json is:
{
"id": "egsPu39L5bLhx3m21t1n",
"userId": "MCetEAeZviyYn5IMYjnp",
"userName": "巽 裕亮",
"content": "フルマラソン完走に対して2018/05/06のふりかえりを行いました!"
}
Trying the same request on postman or chrome gives the expected result (Japanese characters are rendered properly in the output).
But when the data is fetched with Dart by the following code snippet:
import 'dart:convert';
import 'package:http/http.dart' as http;
//irrelevant parts have been omitted
final response = await http.get('SOME URL',headers: {'Content-Type': 'application/json'});
final List<dynamic> responseJson = json.decode(response.body)
print(responseJson);
The result of the print statement in logcat is
{
id: egsPu39L5bLhx3m21t1n,
userId: MCetEAeZviyYn5IMYjnp,
userName: å·½ è£äº®,
content: ãã«ãã©ã½ã³å®èµ°ã«å¯¾ãã¦2018/05/06ã®ãµãããããè¡ãã¾ããï¼
}
Note that only the Japanese characters (value of the content key) is turns into gibberish, the other non-Japanese values are still displayed properly.
Two notices are:
If I try to display this Japanese text in my app via Text(), the same gibberish is rendered, so it is not a fault of Android Studio's logcat.
If I use Text('put some Japanese text here directly') (ex: Text('睡眠')), Flutter displays it correctly, so it is not the Text widget that messes up the Japanese characters.

If you look in postman, you will probably see that the Content-Type http header sent by the server is missing the encoding tag. This causes the Dart http client to decode the body as Latin-1 instead of utf-8. There's a simple workaround:
http.Response response = await http.get('SOME URL',headers: {'Content-Type': 'application/json'});
List<dynamic> responseJson = json.decode(utf8.decode(response.bodyBytes));

So simple!
Instead of using response.body; You should use utf8.decode(response.bodyBytes)

Related

Dart TypeError : type 'JSString' is not a subtype of type 'int' for a Http POST request

I'm building an application using flutter where the user provides a string and a set of values must be returned.
I'm unable to figure out what is the cause for the issue.I tried all the solutions provided to the questions similar to this issue but weren't successful.Any help would be really appreciated.
I converted the actual code to dart only, for easy testing online using dartpad.
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
final body = <String, String>{
"id": '1',
"language": "en",
"text": "I love this service",
};
final headers = <String, String>{
"content-type": "application/json",
"X-RapidAPI-Key": "7f980b3d2cmsh1d666b571febd6ep11df80jsna27f76c06e6b",
"X-RapidAPI-Host": "big-five-personality-insights.p.rapidapi.com",
};
void main(List<String> arguments) async {
final response = await http.post(
Uri.parse('https://big-five-personality-insights.p.rapidapi.com/api/big5'),
headers: headers,
body: [
convert.jsonEncode(body),
],
);
if (response.statusCode == 201) {
// If the server did return a 201 CREATED response,
// then parse the JSON.
print('success');
print(convert.jsonDecode(response.body));
} else {
// If the server did not return a 201 CREATED response,
// then throw an exception.
print('fail');
throw Exception('Failed to get a response.');
}
}
You have a bad value for the body argument of http.post.
The documentation for the method states:
body sets the body of the request. It can be a String, a List or a Map<String, String>. [...] If body is a List, it's used as a list of bytes for the body of the request.
Since the API you are talking to requires an array to be sent, you want to wrap the body in a list before converting it all to json (note how the brackets have shifted inside the convert method:
final response = await http.post(
Uri.parse('https://big-five-personality-insights.p.rapidapi.com/api/big5'),
headers: headers,
body: convert.jsonEncode([body]),
);
Sidenote: The API responds with statusCode 200 on a successful request, not 201; at least in my testing.
The body parameter of a post method 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".
As you passed it as a List, then it expects it to be a List of integers, but you are passing it a List type (or in this specific case List type). Here is a fixed code.
final response = await http.post(
Uri.parse('https://big-five-personality-insights.p.rapidapi.com/api/big5'),
headers: headers,
body: convert.jsonEncode(body),
);

Dart character encoding in http request

Just learning Flutter and running into this issue when trying to call an API:
final response = await http.get(
Uri.https(apiBaseUrl, apiBaseEndpoint + "/tasks"),
headers: {
"Authorization": "Bearer " + apiKey,
},
);
print(response.body);
Part of my response contains Ä°ftar and it's supposed to be İftar. I imagine it's some encoding problem? curl gives me back the response with the proper characters.
Basically: is this a text encoding problem? If so, how do I fix my request?
Ok, after a little bit more digging on the http docs I realized it wasn't in how I made my request that needed to change, but how I handled the response. I was doing
final decodedJson = json.decode(response.body);
and I should've been doing:
final decodedJson = json.decode(utf8.decode(response.bodyBytes));
That has solved my issue!

How to retrieve/decode json/map from downloaded ByteStream?

I have a ByteStream downloaded from a Server, namely datas regarding the user.
Its in MySql server as
"username":"Neor","totalCoins":"350"
The truncated part of .php file that gives-away this data, is as follows:
$data = $stmt->fetchColumn();
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
header("Cache-Control: public");
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-Length:".strlen($data));
echo $data;
I use ths Flutter code to download the data:
Future<void> downloadData() async {
var url = Uri.parse("https://example.com/mycloud.php");
var request = http.MultipartRequest('POST', url)
..fields["user"] = "Dia";
var response = await request.send();
var stream = response.stream; }
On checking if the downloaded ByteStream contains anything, I've used print(stream.length), which prints out as 137.
How can I get the information I want from the ByteStream?
(If my question lacks in any way, please let me know.)
There shouldn't be any need to use a multipart request for a simple POST. Instead use the simpler http.post method.
Future<void> downloadData() async {
final response = await http.post(
Uri.parse('https://example.com/mycloud.php'),
body: <String, String>{
'user': 'Dia',
},
);
final decodedJson = json.decode(response.body);
// if you want to ensure the character set used, replace this with:
// json.decode(utf8.decode(response.bodyBytes));
}
If you do stick with the stream way, you have a Stream<List<int>> that you want to turn initially into a List<int>. Use the toList() method on stream for that. Then you have to decode that into characters. JSON is always encoded in utf8, so you could:
json.decode(utf8.decode(await stream.toList()));
(Under the hood, http is basically doing that for you; collecting the stream together and doing the character decoding and presenting that as body.)
First
import 'dart:convert' show utf8;
String foo = utf8.decode(bytes);
Then
Map valueMap = json.decode(foo );

How to directly print JSON recieved in GET Request Body in Flutter

My intention is to make a GET request using the DIO or any similar HTTP client in order to receive a JSON data/body and print it to the console.
I have written the following code to achieve that.
fetchQuestion(String userIdentifier) async {
String urlToCall =
"someURLhere";
try {
Response response = await Dio().get(
urlToCall,
options: Options(headers: {
HttpHeaders.authorizationHeader: "Bearer " + userIdentifier,
}),
);
print(response.data);
} catch (e) {
print(e);
}
}
The problem with this code is, when I print response.data, only null is printed. Even though I am certain that the response data contains a JSON file.
I have checked on the backend, and I am getting a 200 status code. Additionally, printing response.headers does print the headers I expected. It is only the response.body that prints null.
Issues I have tried include
Using print(utf8.decode(response.data));
Using json.decode(response.data) -> In which case I get
NoSuchMethodError: The getter 'length' was called on null. error.
I would appreciate any kind of help regarding printing the JSON file received.
Have you printed just response to see what fields are in there.
I haven't used DIO but http package works fine for me:
import 'package:http/http.dart' as http;
...
final response = await http.get(Url);

Flutter fetched Japanese character from server decoded wrong

I am building a mobile app with Flutter.
I need to fetch a json file from server which includes Japanese text. A part of the returned json is:
{
"id": "egsPu39L5bLhx3m21t1n",
"userId": "MCetEAeZviyYn5IMYjnp",
"userName": "巽 裕亮",
"content": "フルマラソン完走に対して2018/05/06のふりかえりを行いました!"
}
Trying the same request on postman or chrome gives the expected result (Japanese characters are rendered properly in the output).
But when the data is fetched with Dart by the following code snippet:
import 'dart:convert';
import 'package:http/http.dart' as http;
//irrelevant parts have been omitted
final response = await http.get('SOME URL',headers: {'Content-Type': 'application/json'});
final List<dynamic> responseJson = json.decode(response.body)
print(responseJson);
The result of the print statement in logcat is
{
id: egsPu39L5bLhx3m21t1n,
userId: MCetEAeZviyYn5IMYjnp,
userName: å·½ è£äº®,
content: ãã«ãã©ã½ã³å®èµ°ã«å¯¾ãã¦2018/05/06ã®ãµãããããè¡ãã¾ããï¼
}
Note that only the Japanese characters (value of the content key) is turns into gibberish, the other non-Japanese values are still displayed properly.
Two notices are:
If I try to display this Japanese text in my app via Text(), the same gibberish is rendered, so it is not a fault of Android Studio's logcat.
If I use Text('put some Japanese text here directly') (ex: Text('睡眠')), Flutter displays it correctly, so it is not the Text widget that messes up the Japanese characters.
If you look in postman, you will probably see that the Content-Type http header sent by the server is missing the encoding tag. This causes the Dart http client to decode the body as Latin-1 instead of utf-8. There's a simple workaround:
http.Response response = await http.get('SOME URL',headers: {'Content-Type': 'application/json'});
List<dynamic> responseJson = json.decode(utf8.decode(response.bodyBytes));
So simple!
Instead of using response.body; You should use utf8.decode(response.bodyBytes)