在 HttpClient 中使用 emojis 时显示无效字符使请求变得混乱
Showing invalid characters while using emojis in HttpClient put request in flutter
第一:我的服务器允许 PUT 操作
我在用flutter写一个记忆app(移植swiftUI版本)遇到如下错误
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: Invalid argument (string): Contains invalid characters.:
"[{\"name\":\"user\",\"pass\":\"123\",\"udf\":[{\"colorRed\":255,\"colorGreen\":82,\"colorBlue\":82,\"colorAlpha\":255,\"name\":\"V
ehicles\",\"emojis\":[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"✈️\",\"\",\"⛵️\",\"\",\"\",\"\",\"\",\"
\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],\"chals\":[{\"id\":\"Vehicles-1\",\"disp\":1},{\"id\":\"Vehicles-2\",\"disp\":
2},{\"id\":\"Vehicles-3\",\"disp\":3},{\"id\":\"Vehicles-4\",\"disp\":4},{\"id\":\"Vehicles-5\",\"disp\":5},{\"id\":\"Vehicles-6\",
\"disp\":6},{\"id\":\"Vehicles-7\",\"disp\":7},{\"id\":\"Vehicles-8\",\"disp\":8},{\"id\":\"Vehicles-9\",\"disp\":9},{\"id\":\"Vehi
cles-10\",\"disp\":10},{\"id\":\"Vehicles-11\",\"disp\":11},{\"id\":\"Vehicles-12\",\"disp\":12},{\"id\":\"Vehicles-13\",\"disp\":1
3},{\"id\":\"Vehicles-14\",\"disp\":14},{\"id\":\"Vehicles-15\",\"d<…>
这是flutter doctor --verbose
的结果
flutter doctor --verbose ─╯
[✓] Flutter (Channel beta, 2.13.0-0.4.pre, on macOS 12.3 21E230 darwin-arm,
locale zh-Hans-CN)
• Flutter version 2.13.0-0.4.pre at /Users/jett/flutter
• Upstream repository https://gitee.com/mirrors/Flutter
• FLUTTER_GIT_URL = https://gitee.com/mirrors/Flutter
• Framework revision 25caf1461b (4 weeks ago), 2022-05-05 14:23:09 -0700
• Engine revision c5caf749fe
• Dart version 2.17.0 (build 2.17.0-266.8.beta)
• DevTools version 2.12.2
• Pub download mirror https://pub.flutter-io.cn
• Flutter download mirror https://storage.flutter-io.cn
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/jett/Library/Android/sdk
• Platform android-31, build-tools 31.0.0
• Java binary at:
/Library/Java/JavaVirtualMachines/jdk-11.0.15.1.jdk/Contents/Home/bin/java
• Java version Java(TM) SE Runtime Environment 18.9 (build
11.0.15.1+2-LTS-10)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• CHROME_EXECUTABLE = /Applications/Google Chrome
Canary.app/Contents/MacOS/Google Chrome Canary
[!] Android Studio
• Android Studio at /Applications/Android Studio Preview.app/Contents
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
✗ Unable to find bundled Java version.
• Try updating or re-installing Android Studio.
[✓] VS Code (version 1.68.0-insider)
• VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
• Flutter extension version 3.42.0
[✓] Connected device (3 available)
• iPhone 13 (mobile) • 2A8678B1-09B1-4B43-926F-BA04E5D00790 • ios
• com.apple.CoreSimulator.SimRuntime.iOS-15-5 (simulator)
• macOS (desktop) • macos • darwin-arm64
• macOS 12.3 21E230 darwin-arm
• Chrome (web) • chrome • web-javascript
• Google Chrome 104.0.5102.0 canary
[✓] HTTP Host Availability
• All required HTTP hosts are available
! Doctor found issues in 1 category.
忘记 FLUTTER_GIT_URL
、Pub download mirror
和 Flutter download mirror
相关代码(我在等待调用这个函数):
static Future<void> saveUsers() async {
final HttpClient client = HttpClient();
final HttpClientRequest request = await client.putUrl(Preferences.uri);
request.write(const JsonEncoder().convert(Preferences.users.map((e) => e.toJson()).toList()));
await request.close();
}
// inside the Preferences class
变量和类:
class User {
String name = "";
String pass = "";
List<Theme> udf = [];
User();
User.values(this.name, this.pass, this.udf);
int match(List<User> users) {
for(int i = 0; i < users.length; i++) {
if(users[i].name == name && users[i].pass == pass) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
"name": name,
"pass": pass,
"udf": udf.map((e) => e.toJson()).toList(),
};
String stringfy() => const JsonEncoder().convert(toJson());
factory User.fromJson(Map<String, dynamic> mp) => User.values(
mp["name"] as String,
mp["pass"] as String,
(mp["udf"] as List<dynamic>).map((e) => Theme.fromJson(e as Map<String, dynamic>)).toList(),
);
factory User.fromString(String s) => User.fromJson(const JsonDecoder().convert(s));
}
class Theme {
static List<Color> availableColors = [Colors.redAccent, Colors.blueAccent, Colors.cyan, Colors.orangeAccent, Colors.deepPurple, Colors.green, Colors.indigo, Colors.lime, Colors.pinkAccent.shade100];
Color color = Colors.redAccent;
String name = "";
List<String> emojis = [];
final int id;
List<Challange> chals = [];
int gotToChal = 0;
int score = 0;
static int idCount = 0;
Theme() : id = Theme.idCount {
idCount += 1;
}
Theme.values(this.color, this.name, this.emojis, this.chals, this.gotToChal, this.score) : id = Theme.idCount {
idCount += 1;
}
int match(List<Theme> themes) {
for(int i = 0; i < themes.length; i++) {
if(themes[i].id == id) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
'colorRed': color.red,
'colorGreen': color.green,
'colorBlue': color.blue,
'colorAlpha': color.alpha,
'name': name,
'emojis': emojis,
'chals': chals.map((e) => e.toJson()).toList(),
'gotToChal': gotToChal,
'score': score,
};
String stringfy() => const JsonEncoder().convert(toJson());
factory Theme.fromJson(Map<String, dynamic> mp) => Theme.values(
Color.fromARGB(
mp['colorAlpha'] as int,
mp['colorRed'] as int,
mp['colorGreen'] as int,
mp['colorBlue'] as int
),
mp['name'] as String,
(mp['emojis'] as List<dynamic>).map((e) => e as String).toList(),
(mp['chals'] as List<dynamic>).map((e) => Challange.fromJson(e as Map<String, dynamic>)).toList(),
mp['gotToChal'] as int,
mp['score'] as int,
);
factory Theme.fromString(String s) => Theme.fromJson(const JsonDecoder().convert(s));
static final List<Theme> defaultThemes = [
Theme.values(
Colors.redAccent,
"Vehicles",
["", "", "", "", "", "", "", "", "✈️", "", "⛵️", "", "", "", "", "", "", "", "", "", "", "", ""],
List.generate(21, (index) => index+1).map((e) => Challange.preset("Vehicles-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.orangeAccent,
"Fast Food",
["", "", "", "", "", "", "", "", "", "", "", ""],
List.generate(10, (index) => index+1).map((e) => Challange.preset("FastFood-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.green,
"Drinks",
["", "☕️", "", "", "", "", "", "", "", ""],
List.generate(8, (index) => index+1).map((e) => Challange.preset("Drinks-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.cyan,
"Fruits",
["", "", "", "", "", "", "", "", "", ""],
List.generate(8, (index) => index+1).map((e) => Challange.preset("Fruits-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.blueAccent,
"Vegetables",
["", "", "", "", "", "", "", ""],
List.generate(6, (index) => index+1).map((e) => Challange.preset("Vegetables-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.pinkAccent.shade100,
"Animals",
["", "", "", "", "", "", "", "", "", "", ""],
List.generate(9, (index) => index+1).map((e) => Challange.preset("Animals-$e", e)).toList(),
0,
0,
),
];
}
class Challange {
final String id;
final int disp;
Challange(this.id, this.disp);
Challange.preset(this.id, this.disp);
get nCards => min(min(2 + disp, 20), Game.theme.emojis.length);
get bonusTime => Duration(milliseconds: ((6 + ((disp-1)/3))*1000).floor());
int match(List<Challange> chals) {
for(int i = 0; i < chals.length; i++) {
if(chals[i].id == id) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
'id': id,
'disp': disp
};
String stringfy() => const JsonEncoder().convert(toJson());
factory Challange.fromJson(Map<String, dynamic> mp) => Challange.preset(
mp['id'] as String,
mp['disp'] as int
);
factory Challange.fromString(String s) => Challange.fromJson(const JsonDecoder().convert(s));
}
// following in Preferences
static final Uri uri = Uri.parse("https://www.openwld.com/memorize.json");
static late SharedPreferences prefs;
static User user = User.values("nothing", "none", Theme.defaultThemes);
static late List<User> users;
static List<Theme> get themes => user.udf;
static set themes(List<Theme> newValue) {
user.udf = newValue;
}
static const String _name = "memorize_user";
我要放的内容:
[{"name":"user","pass":"123","udf":[{"colorRed":255,"colorGreen":82,"colorBlue":82,"colorAlpha":255,"name":"Vehicles","emojis":["","","","","","","","","✈️","","⛵️","","","","","","","","","","","",""],"chals":[{"id":"Vehicles-1","disp":1},{"id":"Vehicles-2","disp":2},{"id":"Vehicles-3","disp":3},{"id":"Vehicles-4","disp":4},{"id":"Vehicles-5","disp":5},{"id":"Vehicles-6","disp":6},{"id":"Vehicles-7","disp":7},{"id":"Vehicles-8","disp":8},{"id":"Vehicles-9","disp":9},{"id":"Vehicles-10","disp":10},{"id":"Vehicles-11","disp":11},{"id":"Vehicles-12","disp":12},{"id":"Vehicles-13","disp":13},{"id":"Vehicles-14","disp":14},{"id":"Vehicles-15","disp":15},{"id":"Vehicles-16","disp":16},{"id":"Vehicles-17","disp":17},{"id":"Vehicles-18","disp":18},{"id":"Vehicles-19","disp":19},{"id":"Vehicles-20","disp":20},{"id":"Vehicles-21","disp":21}],"gotToChal":0,"score":0},{"colorRed":255,"colorGreen":171,"colorBlue":64,"colorAlpha":255,"name":"Fast Food","emojis":["","","","","","","","","","","",""],"chals":[{"id":"FastFood-1","disp":1},{"id":"FastFood-2","disp":2},{"id":"FastFood-3","disp":3},{"id":"FastFood-4","disp":4},{"id":"FastFood-5","disp":5},{"id":"FastFood-6","disp":6},{"id":"FastFood-7","disp":7},{"id":"FastFood-8","disp":8},{"id":"FastFood-9","disp":9},{"id":"FastFood-10","disp":10}],"gotToChal":0,"score":0},{"colorRed":76,"colorGreen":175,"colorBlue":80,"colorAlpha":255,"name":"Drinks","emojis":["","☕️","","","","","","","",""],"chals":[{"id":"Drinks-1","disp":1},{"id":"Drinks-2","disp":2},{"id":"Drinks-3","disp":3},{"id":"Drinks-4","disp":4},{"id":"Drinks-5","disp":5},{"id":"Drinks-6","disp":6},{"id":"Drinks-7","disp":7},{"id":"Drinks-8","disp":8}],"gotToChal":0,"score":0},{"colorRed":0,"colorGreen":188,"colorBlue":212,"colorAlpha":255,"name":"Fruits","emojis":["","","","","","","","","",""],"chals":[{"id":"Fruits-1","disp":1},{"id":"Fruits-2","disp":2},{"id":"Fruits-3","disp":3},{"id":"Fruits-4","disp":4},{"id":"Fruits-5","disp":5},{"id":"Fruits-6","disp":6},{"id":"Fruits-7","disp":7},{"id":"Fruits-8","disp":8}],"gotToChal":0,"score":0},{"colorRed":68,"colorGreen":138,"colorBlue":255,"colorAlpha":255,"name":"Vegetables","emojis":["","","","","","","",""],"chals":[{"id":"Vegetables-1","disp":1},{"id":"Vegetables-2","disp":2},{"id":"Vegetables-3","disp":3},{"id":"Vegetables-4","disp":4},{"id":"Vegetables-5","disp":5},{"id":"Vegetables-6","disp":6}],"gotToChal":0,"score":0},{"colorRed":255,"colorGreen":128,"colorBlue":171,"colorAlpha":255,"name":"Animals","emojis":["","","","","","","","","","",""],"chals":[{"id":"Animals-1","disp":1},{"id":"Animals-2","disp":2},{"id":"Animals-3","disp":3},{"id":"Animals-4","disp":4},{"id":"Animals-5","disp":5},{"id":"Animals-6","disp":6},{"id":"Animals-7","disp":7},{"id":"Animals-8","disp":8},{"id":"Animals-9","disp":9}],"gotToChal":0,"score":0}]}]
您使用的是默认编码,即 ISO-8859-1 而不是 UTF-8。在调用 write
之前,您需要正确设置字符集:
request.headers.contentType =
ContentType('application', 'json', charset: 'utf-8');
Flutter 将从该字符集中检测用于序列化数据的编码。
来源:Flutter docs
第一:我的服务器允许 PUT 操作
我在用flutter写一个记忆app(移植swiftUI版本)遇到如下错误
[VERBOSE-2:ui_dart_state.cc(198)] Unhandled Exception: Invalid argument (string): Contains invalid characters.:
"[{\"name\":\"user\",\"pass\":\"123\",\"udf\":[{\"colorRed\":255,\"colorGreen\":82,\"colorBlue\":82,\"colorAlpha\":255,\"name\":\"V
ehicles\",\"emojis\":[\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"\",\"✈️\",\"\",\"⛵️\",\"\",\"\",\"\",\"\",\"
\",\"\",\"\",\"\",\"\",\"\",\"\",\"\"],\"chals\":[{\"id\":\"Vehicles-1\",\"disp\":1},{\"id\":\"Vehicles-2\",\"disp\":
2},{\"id\":\"Vehicles-3\",\"disp\":3},{\"id\":\"Vehicles-4\",\"disp\":4},{\"id\":\"Vehicles-5\",\"disp\":5},{\"id\":\"Vehicles-6\",
\"disp\":6},{\"id\":\"Vehicles-7\",\"disp\":7},{\"id\":\"Vehicles-8\",\"disp\":8},{\"id\":\"Vehicles-9\",\"disp\":9},{\"id\":\"Vehi
cles-10\",\"disp\":10},{\"id\":\"Vehicles-11\",\"disp\":11},{\"id\":\"Vehicles-12\",\"disp\":12},{\"id\":\"Vehicles-13\",\"disp\":1
3},{\"id\":\"Vehicles-14\",\"disp\":14},{\"id\":\"Vehicles-15\",\"d<…>
这是flutter doctor --verbose
flutter doctor --verbose ─╯
[✓] Flutter (Channel beta, 2.13.0-0.4.pre, on macOS 12.3 21E230 darwin-arm,
locale zh-Hans-CN)
• Flutter version 2.13.0-0.4.pre at /Users/jett/flutter
• Upstream repository https://gitee.com/mirrors/Flutter
• FLUTTER_GIT_URL = https://gitee.com/mirrors/Flutter
• Framework revision 25caf1461b (4 weeks ago), 2022-05-05 14:23:09 -0700
• Engine revision c5caf749fe
• Dart version 2.17.0 (build 2.17.0-266.8.beta)
• DevTools version 2.12.2
• Pub download mirror https://pub.flutter-io.cn
• Flutter download mirror https://storage.flutter-io.cn
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
• Android SDK at /Users/jett/Library/Android/sdk
• Platform android-31, build-tools 31.0.0
• Java binary at:
/Library/Java/JavaVirtualMachines/jdk-11.0.15.1.jdk/Contents/Home/bin/java
• Java version Java(TM) SE Runtime Environment 18.9 (build
11.0.15.1+2-LTS-10)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.3
[✓] Chrome - develop for the web
• CHROME_EXECUTABLE = /Applications/Google Chrome
Canary.app/Contents/MacOS/Google Chrome Canary
[!] Android Studio
• Android Studio at /Applications/Android Studio Preview.app/Contents
• Flutter plugin can be installed from:
https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
https://plugins.jetbrains.com/plugin/6351-dart
✗ Unable to find bundled Java version.
• Try updating or re-installing Android Studio.
[✓] VS Code (version 1.68.0-insider)
• VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
• Flutter extension version 3.42.0
[✓] Connected device (3 available)
• iPhone 13 (mobile) • 2A8678B1-09B1-4B43-926F-BA04E5D00790 • ios
• com.apple.CoreSimulator.SimRuntime.iOS-15-5 (simulator)
• macOS (desktop) • macos • darwin-arm64
• macOS 12.3 21E230 darwin-arm
• Chrome (web) • chrome • web-javascript
• Google Chrome 104.0.5102.0 canary
[✓] HTTP Host Availability
• All required HTTP hosts are available
! Doctor found issues in 1 category.
忘记 FLUTTER_GIT_URL
、Pub download mirror
和 Flutter download mirror
相关代码(我在等待调用这个函数):
static Future<void> saveUsers() async {
final HttpClient client = HttpClient();
final HttpClientRequest request = await client.putUrl(Preferences.uri);
request.write(const JsonEncoder().convert(Preferences.users.map((e) => e.toJson()).toList()));
await request.close();
}
// inside the Preferences class
变量和类:
class User {
String name = "";
String pass = "";
List<Theme> udf = [];
User();
User.values(this.name, this.pass, this.udf);
int match(List<User> users) {
for(int i = 0; i < users.length; i++) {
if(users[i].name == name && users[i].pass == pass) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
"name": name,
"pass": pass,
"udf": udf.map((e) => e.toJson()).toList(),
};
String stringfy() => const JsonEncoder().convert(toJson());
factory User.fromJson(Map<String, dynamic> mp) => User.values(
mp["name"] as String,
mp["pass"] as String,
(mp["udf"] as List<dynamic>).map((e) => Theme.fromJson(e as Map<String, dynamic>)).toList(),
);
factory User.fromString(String s) => User.fromJson(const JsonDecoder().convert(s));
}
class Theme {
static List<Color> availableColors = [Colors.redAccent, Colors.blueAccent, Colors.cyan, Colors.orangeAccent, Colors.deepPurple, Colors.green, Colors.indigo, Colors.lime, Colors.pinkAccent.shade100];
Color color = Colors.redAccent;
String name = "";
List<String> emojis = [];
final int id;
List<Challange> chals = [];
int gotToChal = 0;
int score = 0;
static int idCount = 0;
Theme() : id = Theme.idCount {
idCount += 1;
}
Theme.values(this.color, this.name, this.emojis, this.chals, this.gotToChal, this.score) : id = Theme.idCount {
idCount += 1;
}
int match(List<Theme> themes) {
for(int i = 0; i < themes.length; i++) {
if(themes[i].id == id) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
'colorRed': color.red,
'colorGreen': color.green,
'colorBlue': color.blue,
'colorAlpha': color.alpha,
'name': name,
'emojis': emojis,
'chals': chals.map((e) => e.toJson()).toList(),
'gotToChal': gotToChal,
'score': score,
};
String stringfy() => const JsonEncoder().convert(toJson());
factory Theme.fromJson(Map<String, dynamic> mp) => Theme.values(
Color.fromARGB(
mp['colorAlpha'] as int,
mp['colorRed'] as int,
mp['colorGreen'] as int,
mp['colorBlue'] as int
),
mp['name'] as String,
(mp['emojis'] as List<dynamic>).map((e) => e as String).toList(),
(mp['chals'] as List<dynamic>).map((e) => Challange.fromJson(e as Map<String, dynamic>)).toList(),
mp['gotToChal'] as int,
mp['score'] as int,
);
factory Theme.fromString(String s) => Theme.fromJson(const JsonDecoder().convert(s));
static final List<Theme> defaultThemes = [
Theme.values(
Colors.redAccent,
"Vehicles",
["", "", "", "", "", "", "", "", "✈️", "", "⛵️", "", "", "", "", "", "", "", "", "", "", "", ""],
List.generate(21, (index) => index+1).map((e) => Challange.preset("Vehicles-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.orangeAccent,
"Fast Food",
["", "", "", "", "", "", "", "", "", "", "", ""],
List.generate(10, (index) => index+1).map((e) => Challange.preset("FastFood-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.green,
"Drinks",
["", "☕️", "", "", "", "", "", "", "", ""],
List.generate(8, (index) => index+1).map((e) => Challange.preset("Drinks-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.cyan,
"Fruits",
["", "", "", "", "", "", "", "", "", ""],
List.generate(8, (index) => index+1).map((e) => Challange.preset("Fruits-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.blueAccent,
"Vegetables",
["", "", "", "", "", "", "", ""],
List.generate(6, (index) => index+1).map((e) => Challange.preset("Vegetables-$e", e)).toList(),
0,
0,
),
Theme.values(
Colors.pinkAccent.shade100,
"Animals",
["", "", "", "", "", "", "", "", "", "", ""],
List.generate(9, (index) => index+1).map((e) => Challange.preset("Animals-$e", e)).toList(),
0,
0,
),
];
}
class Challange {
final String id;
final int disp;
Challange(this.id, this.disp);
Challange.preset(this.id, this.disp);
get nCards => min(min(2 + disp, 20), Game.theme.emojis.length);
get bonusTime => Duration(milliseconds: ((6 + ((disp-1)/3))*1000).floor());
int match(List<Challange> chals) {
for(int i = 0; i < chals.length; i++) {
if(chals[i].id == id) {
return i;
}
}
return -1;
}
Map<String, dynamic> toJson() => {
'id': id,
'disp': disp
};
String stringfy() => const JsonEncoder().convert(toJson());
factory Challange.fromJson(Map<String, dynamic> mp) => Challange.preset(
mp['id'] as String,
mp['disp'] as int
);
factory Challange.fromString(String s) => Challange.fromJson(const JsonDecoder().convert(s));
}
// following in Preferences
static final Uri uri = Uri.parse("https://www.openwld.com/memorize.json");
static late SharedPreferences prefs;
static User user = User.values("nothing", "none", Theme.defaultThemes);
static late List<User> users;
static List<Theme> get themes => user.udf;
static set themes(List<Theme> newValue) {
user.udf = newValue;
}
static const String _name = "memorize_user";
我要放的内容:
[{"name":"user","pass":"123","udf":[{"colorRed":255,"colorGreen":82,"colorBlue":82,"colorAlpha":255,"name":"Vehicles","emojis":["","","","","","","","","✈️","","⛵️","","","","","","","","","","","",""],"chals":[{"id":"Vehicles-1","disp":1},{"id":"Vehicles-2","disp":2},{"id":"Vehicles-3","disp":3},{"id":"Vehicles-4","disp":4},{"id":"Vehicles-5","disp":5},{"id":"Vehicles-6","disp":6},{"id":"Vehicles-7","disp":7},{"id":"Vehicles-8","disp":8},{"id":"Vehicles-9","disp":9},{"id":"Vehicles-10","disp":10},{"id":"Vehicles-11","disp":11},{"id":"Vehicles-12","disp":12},{"id":"Vehicles-13","disp":13},{"id":"Vehicles-14","disp":14},{"id":"Vehicles-15","disp":15},{"id":"Vehicles-16","disp":16},{"id":"Vehicles-17","disp":17},{"id":"Vehicles-18","disp":18},{"id":"Vehicles-19","disp":19},{"id":"Vehicles-20","disp":20},{"id":"Vehicles-21","disp":21}],"gotToChal":0,"score":0},{"colorRed":255,"colorGreen":171,"colorBlue":64,"colorAlpha":255,"name":"Fast Food","emojis":["","","","","","","","","","","",""],"chals":[{"id":"FastFood-1","disp":1},{"id":"FastFood-2","disp":2},{"id":"FastFood-3","disp":3},{"id":"FastFood-4","disp":4},{"id":"FastFood-5","disp":5},{"id":"FastFood-6","disp":6},{"id":"FastFood-7","disp":7},{"id":"FastFood-8","disp":8},{"id":"FastFood-9","disp":9},{"id":"FastFood-10","disp":10}],"gotToChal":0,"score":0},{"colorRed":76,"colorGreen":175,"colorBlue":80,"colorAlpha":255,"name":"Drinks","emojis":["","☕️","","","","","","","",""],"chals":[{"id":"Drinks-1","disp":1},{"id":"Drinks-2","disp":2},{"id":"Drinks-3","disp":3},{"id":"Drinks-4","disp":4},{"id":"Drinks-5","disp":5},{"id":"Drinks-6","disp":6},{"id":"Drinks-7","disp":7},{"id":"Drinks-8","disp":8}],"gotToChal":0,"score":0},{"colorRed":0,"colorGreen":188,"colorBlue":212,"colorAlpha":255,"name":"Fruits","emojis":["","","","","","","","","",""],"chals":[{"id":"Fruits-1","disp":1},{"id":"Fruits-2","disp":2},{"id":"Fruits-3","disp":3},{"id":"Fruits-4","disp":4},{"id":"Fruits-5","disp":5},{"id":"Fruits-6","disp":6},{"id":"Fruits-7","disp":7},{"id":"Fruits-8","disp":8}],"gotToChal":0,"score":0},{"colorRed":68,"colorGreen":138,"colorBlue":255,"colorAlpha":255,"name":"Vegetables","emojis":["","","","","","","",""],"chals":[{"id":"Vegetables-1","disp":1},{"id":"Vegetables-2","disp":2},{"id":"Vegetables-3","disp":3},{"id":"Vegetables-4","disp":4},{"id":"Vegetables-5","disp":5},{"id":"Vegetables-6","disp":6}],"gotToChal":0,"score":0},{"colorRed":255,"colorGreen":128,"colorBlue":171,"colorAlpha":255,"name":"Animals","emojis":["","","","","","","","","","",""],"chals":[{"id":"Animals-1","disp":1},{"id":"Animals-2","disp":2},{"id":"Animals-3","disp":3},{"id":"Animals-4","disp":4},{"id":"Animals-5","disp":5},{"id":"Animals-6","disp":6},{"id":"Animals-7","disp":7},{"id":"Animals-8","disp":8},{"id":"Animals-9","disp":9}],"gotToChal":0,"score":0}]}]
您使用的是默认编码,即 ISO-8859-1 而不是 UTF-8。在调用 write
之前,您需要正确设置字符集:
request.headers.contentType =
ContentType('application', 'json', charset: 'utf-8');
Flutter 将从该字符集中检测用于序列化数据的编码。
来源:Flutter docs