You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter报错:Null不是String子类型的问题解决求助

解决Flutter中"type 'Null' is not a subtype of type 'String'"错误

错误日志

E/flutter ( 5602): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'String'
E/flutter ( 5602): #0      new Data.fromJson
package:siakad_masoem_university/models/transkrip_nilai.dart:188
E/flutter ( 5602): #1      new NilaiMahasiswa.fromJson.<anonymous closure>
package:siakad_masoem_university/models/transkrip_nilai.dart:120
E/flutter ( 5602): #2      List.forEach (dart:core-patch/growable_array.dart:416:8)
E/flutter ( 5602): #3      new NilaiMahasiswa.fromJson
package:siakad_masoem_university/models/transkrip_nilai.dart:119
E/flutter ( 5602): #4      Services.getNilaiMahasiswa
package:siakad_masoem_university/provider/services.dart:128
E/flutter ( 5602): <asynchronous suspension>
E/flutter ( 5602): #5      _NilaiMahasiswaPageState.fetchData
package:siakad_masoem_university/…/akademik/transkrip_nilai.dart:62
E/flutter ( 5602): <asynchronous suspension>

该错误在修改求和代码后触发,以下是相关代码片段:

修改后的求和代码

int getSum() {
  final uts = data.first.nilaiIndeksUts;
  final akhir = data.first.nilaiIndeksAkhir;
  // int? uts = int.tryParse(data.first.nilaiIndeksUts ?? '');
  // int? akhir = int.tryParse(data.first.nilaiIndeksAkhir ?? '');
  return (uts ?? 0) + (akhir ?? 0);
}

数据加载代码

fetchData(int smt) async {
  final apiResponse = await Services().getNilaiMahasiswa(smt);
  setState(() {
    data = (apiResponse.data!);
  });
}

结果展示代码

Text(
  getSum().toString(),
  style: bold6,
),

API调用代码

Future<NilaiMahasiswa> getNilaiMahasiswa(int semester) async {
  String url = Constant.baseURL;
  String token = await UtilSharedPreferences.getToken();
  final response = await http.get(
    Uri.parse(
      '$url/auth/mhs_siakad/transkrip_nilai?semester=$semester',
    ),
    headers: {
      'Authorization': 'Bearer $token',
    },
  );

  print(response.statusCode);
  print(response.body);
  if (response.statusCode == 200) {
    return NilaiMahasiswa.fromJson(jsonDecode(response.body));
  } else {
    throw Exception();
  }
}

Dart模型代码

class NilaiMahasiswa {
  String? status;
  String? code;
  List<Data>? data;

  NilaiMahasiswa({this.status, this.code, this.data});

  NilaiMahasiswa.fromJson(Map<String, dynamic> json) {
    status = json['status'];
    code = json['code'];
    if (json['data'] != null) {
      data = <Data>[];
      json['data'].forEach((v) {
        data!.add(Data.fromJson(v));
      });
    }
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['status'] = status;
    data['code'] = code;
    if (this.data != null) {
      data['data'] = this.data!.map((v) => v.toJson()).toList();
    }
    return data;
  }
}

class Data {
  String? idTranskripNilai;
  String? idMk;
  String? kodeMk;
  String? nmMk;
  int? sks;
  int? smt;
  String? nilaiAkhirUts;
  String? nilaiHurufUts;
  int? nilaiIndeksUts; // convert it to int the moment you receive the data
  String? nilaiAkhirUas;
  String? nilaiAkhir;
  String? nilaiHurufAkhir;
  int? nilaiIndeksAkhir; // convert it to int the moment you receive thedata
  int? statusNilaiAkhir;
  int? statusNilaiUts;
  String? updatedBy;
  int? summationResult;

  Data(
      {this.idTranskripNilai,
      this.idMk,
      this.kodeMk,
      this.nmMk,
      this.sks,
      this.smt,
      this.nilaiAkhirUts,
      this.nilaiHurufUts,
      this.nilaiIndeksUts,
      this.nilaiAkhirUas,
      this.nilaiAkhir,
      this.nilaiHurufAkhir,
      this.nilaiIndeksAkhir,
      this.statusNilaiAkhir,
      this.statusNilaiUts,
      this.updatedBy});

  Data.fromJson(Map<String, dynamic> json) {
    idTranskripNilai = json['id_transkrip_nilai'];
    idMk = json['id_mk'];
    kodeMk = json['kode_mk'];
    nmMk = json['nm_mk'];
    sks = json['sks'];
    smt = json['smt'];
    nilaiAkhirUts = json['nilai_akhir_uts'];
    nilaiHurufUts = json['nilai_huruf_uts'];
// converting to int
    nilaiIndeksUts = int.tryParse(json['nilai_indeks_uts']);
    nilaiAkhirUas = json['nilai_akhir_uas'];
    nilaiAkhir = json['nilai_akhir'];
    nilaiHurufAkhir = json['nilai_huruf_akhir'];
// converting to int
    nilaiIndeksAkhir = int.tryParse(json['nilai_indeks_akhir']);
    statusNilaiAkhir = json['status_nilai_akhir'];
    statusNilaiUts = json['status_nilai_uts'];
    updatedBy = json['updated_by'];
    summationResult = nilaiIndeksAkhir! + nilaiIndeksUts!;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = <String, dynamic>{};
    data['id_transkrip_nilai'] = this.idTranskripNilai;
    data['id_mk'] = this.idMk;
    data['kode_mk'] = this.kodeMk;
    data['nm_mk'] = this.nmMk;
    data['sks'] = this.sks;
    data['smt'] = this.smt;
    data['nilai_akhir_uts'] = this.nilaiAkhirUts;
    data['nilai_huruf_uts'] = this.nilaiHurufUts;
    data['nilai_indeks_uts'] = this.nilaiIndeksUts;
    data['nilai_akhir_uas'] = this.nilaiAkhirUas;
    data['nilai_akhir'] = this.nilaiAkhir;
    data['nilai_huruf_akhir'] = this.nilaiHurufAkhir;
    data['nilai_indeks_akhir'] = this.nilaiIndeksAkhir;
    data['status_nilai_akhir'] = this.statusNilaiAkhir;
    data['status_nilai_uts'] = this.statusNilaiUts;
    data['updated_by'] = this.updatedBy;
    return data;
  }
}

错误原因

错误指向Data.fromJson的类型转换逻辑:

  1. int.tryParse要求参数为String类型,但API返回的nilai_indeks_uts/nilai_indeks_akhir可能是null、数字类型(int),导致类型不匹配。
  2. summationResult = nilaiIndeksAkhir! + nilaiIndeksUts!使用强制解包,若字段为null会触发空指针。

解决步骤

1. 安全处理类型转换

修改Data.fromJson中的类型转换代码,兼容String、int、null三种情况:

// 处理nilai_indeks_uts
final utsIndeks = json['nilai_indeks_uts'];
nilaiIndeksUts = utsIndeks is String 
  ? int.tryParse(utsIndeks) ?? 0 
  : (utsIndeks is int ? utsIndeks : 0);

// 处理nilai_indeks_akhir
final akhirIndeks = json['nilai_indeks_akhir'];
nilaiIndeksAkhir = akhirIndeks is String 
  ? int.tryParse(akhirIndeks) ?? 0 
  : (akhirIndeks is int ? akhirIndeks : 0);

2. 移除强制解包,处理null值

修改summationResult的赋值逻辑:

summationResult = (nilaiIndeksAkhir ?? 0) + (nilaiIndeksUts ?? 0);

3. 数据加载时的安全判断

避免强制解包apiResponse.data,为空时赋值空列表:

fetchData(int smt) async {
  final apiResponse = await Services().getNilaiMahasiswa(smt);
  setState(() {
    data = apiResponse.data ?? [];
  });
}

4. 求和函数的空列表判断

防止data.first在空列表时报错:

int getSum() {
  if (data.isEmpty) return 0;
  final uts = data.first.nilaiIndeksUts;
  final akhir = data.first.nilaiIndeksAkhir;
  return (uts ?? 0) + (akhir ?? 0);
}

内容的提问来源于stack exchange,提问作者sharon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:20:42