从服务器颤动中获取用户数据

fetch user data from server flutter

我正在按照开发人员 docs 的教程从互联网上获取数据,但我无法解码对 User 对象的响应。

由于我使用 Postman 检查 API 我可以告诉你我的请求已成功收到并且服务器响应我 200 和一个充满数据的正文(nameidtoken) 但是当我尝试在 try-catch 块中调用 fromJson 方法来创建 User 对象时,它失败了,这个错误是印刷:

flutter: Response 200
flutter: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'

这是我的用户 class :

  class User extends Equatable {
  final String token;
  final String name;
  final String id;

  const User({
    required this.token,
    required this.name,
    required this.id,
  });

  static const User empty = User(token: "token", name: "name", id: "id");

  Map<String, dynamic> toMap() {
    return <String, String>{
      'token': token,
      'name': name,
      'id': id,
    };
  }

  factory User.fromMap(Map<String, dynamic> json) {
    return User(
      token: json['token'] ?? "token",
      name: json['name'] ?? "name",
      id: json['id'] ?? "id",
    );
  }

  String toJson() => json.encode(toMap());

  factory User.fromJson(Map<String, dynamic> jsonMap) => User.fromMap(jsonMap);

  @override
  String toString() {
    return token + ' ' + name + ' ' + id + '\n';
  }

  @override
  List<Object?> get props => [token, name, id];
}

UserCredentials 这只是用户名和密码的包装器:

class UserCredentials {
  final String name;
  final String email;
  final String password;
  UserCredentials(
      {required this.name, required this.email, required this.password});

  factory UserCredentials.fromJson(Map<String, dynamic> json) {
    return UserCredentials(
      name: json['name'] as String,
      email: json['email'] as String,
      password: json['password'] as String,
    );
  }
  Map<String, String> toJsonRegistration() {
    return {
      "name": name,
      "email": email,
      "password": password,
    };
  }

  Map<String, String> toJsonLogin() {
    return {
      "email": email,
      "password": password,
    };
  }

  @override
  String toString() {
    return name + " " + email + " " + password + '\n';
  }
}

这是我用来从服务器获取数据的 user_repository 函数:

     Future<User> _login(UserCredentials user) async {
    User? userFetched;
    //print(user);
    http.Response response = await http.post(
      Uri.parse("http://link_to_repo"),
      body: user.toJsonLogin(),
    );
    print("Inizio");
    print((response.body));
    print(jsonDecode(response.body));
    print(User.fromJson(jsonDecode(response.body)));
    print("fine");
    if (response.statusCode == 200) {
      print(response.statusCode);
      try {
        userFetched = User.fromJson(jsonDecode(response.body));
        print(userFetched);
      } catch (e) {
        print(e);
      }
      print("End");
      return userFetched!;
    } else {
      print("Login Failure from repository");
      throw Exception("Email already taken");
    }
  }

正如您在上面看到的,它能够打印“Response 200”,但无法成功完成 try-catch 块内的操作。

编辑:

这是 response.body :

{"data" : {"token":"50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz","name":"test","id":1}}

jsonDecode(response.body))

{data: {token: 50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz, name: test, id: 1}}

解决方案:

这个post有点混乱但要清楚:

Clucera 给了我获取数据和创建 User 对象的确切解决方案,所以我接受了它的答案。

Josip Domazet的回答帮助我修复了错误,但他没有解决问题,因为我仍然无法创建 User 数据。

jsonDecode(response.body) 会 return 一个 Map。但是,您的构造函数 User.fromJsonString 作为参数。解码一次就足够了,从那时起你就可以使用你已经拥有的 Map 了。所以不需要在 fromJson 中再次调用 jsonDecode,这应该可以正常工作:

 factory User.fromJson(Map<String, dynamic> jsonMap) =>
      User.fromMap(jsonMap);

如果我们查看您的异常,它会告诉我们:

flutter: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'

您的构造函数需要一个 String 但收到一个映射 (_InternalLinkedHashMap)。

查看您的代码,您似乎在执行以下操作

User.fromJson(jsonDecode(response.body));

然后您将使用以下工厂创建 User 实例

 factory User.fromMap(Map<String, dynamic> json) {
    return User(
      token: json['token'] ?? "token",
      name: json['name'] ?? "name",
      id: json['id'] ?? "id",
  );

问题是您的 Json 包含在另一个名为“数据”的 json 中,如您的打印响应所示

{data: {token: 50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz, name: test, id: 1}}

在这种情况下,您有两种解决方案,要么将键嵌套在构造函数中(不建议您采用这种方法)

 factory User.fromMap(Map<String, dynamic> json) {
    return User(
      token: json['data']['token'] ?? "token",
      name: json['data']['name'] ?? "name",
      id: json['data']['id'] ?? "id",
  );

或者在你解析 json 的地方你可以直接提取 data json (我建议你这个选项)

User.fromJson(jsonDecode(response.body)['data']);