Flutter(Dart)中使用类无法从JSON获取数据问题求助
问题:用生成的Dart类解析天气API数据时,temperature字段返回null
成功获取weatherstack API的完整JSON响应,但通过生成的Current类访问temperature时输出null。
代码示例
获取数据的方法:
Future<Current> getweatherData({required String location}) async { final _response = await http.get(Uri.parse( 'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location')); print(_response.body); // 打印API响应 final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>; final _data = Current.fromJson(_bodyJson); print(_data.temperature); // 输出null return _data; }
生成的Current类:
import 'package:json_annotation/json_annotation.dart'; part 'current.g.dart'; @JsonSerializable() class Current { @JsonKey(name: 'observation_time') String? observationTime; int? temperature; @JsonKey(name: 'weather_code') int? weatherCode; @JsonKey(name: 'weather_icons') List<String>? weatherIcons; @JsonKey(name: 'weather_descriptions') List<String>? weatherDescriptions; @JsonKey(name: 'wind_speed') int? windSpeed; @JsonKey(name: 'wind_degree') int? windDegree; @JsonKey(name: 'wind_dir') String? windDir; int? pressure; int? precip; int? humidity; int? cloudcover; int? feelslike; @JsonKey(name: 'uv_index') int? uvIndex; int? visibility; @JsonKey(name: 'is_day') String? isDay; Current({ this.observationTime, this.temperature, this.weatherCode, this.weatherIcons, this.weatherDescriptions, this.windSpeed, this.windDegree, this.windDir, this.pressure, this.precip, this.humidity, this.cloudcover, this.feelslike, this.uvIndex, this.visibility, this.isDay, }); factory Current.fromJson(Map<String, dynamic> json) { return _$CurrentFromJson(json); } Map<String, dynamic> toJson() => _$CurrentToJson(this); }
问题原因
weatherstack的API响应是嵌套结构,所有天气数据都在顶层的current字段中,响应大致结构如下:
{ "request": {...}, "location": {...}, "current": { "temperature": 22, "observation_time": "09:45 AM", ... } }
你直接把整个顶层JSON Map传给Current.fromJson,但Current类的字段对应是current子Map里的键,自然匹配不到,所以temperature返回null。
解决方案
方法1:直接提取current子Map解析
修改获取数据的代码,先从顶层Map中取出current对应的子Map,再传给Current.fromJson:
Future<Current> getweatherData({required String location}) async { final _response = await http.get(Uri.parse( 'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location')); print(_response.body); final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>; // 提取current子Map final _currentJson = _bodyJson['current'] as Map<String, dynamic>; final _data = Current.fromJson(_currentJson); print(_data.temperature); // 现在能正确输出温度值 return _data; }
方法2:生成完整的响应类(推荐)
如果需要用到request、location等其他字段,可以生成包含整个响应结构的类:
import 'package:json_annotation/json_annotation.dart'; import 'current.dart'; part 'weather_response.g.dart'; @JsonSerializable() class WeatherResponse { Map<String, dynamic>? request; Map<String, dynamic>? location; Current? current; WeatherResponse({this.request, this.location, this.current}); factory WeatherResponse.fromJson(Map<String, dynamic> json) => _$WeatherResponseFromJson(json); Map<String, dynamic> toJson() => _$WeatherResponseToJson(this); }
然后修改获取数据的代码:
Future<Current> getweatherData({required String location}) async { final _response = await http.get(Uri.parse( 'http://api.weatherstack.com/current?access_key=a80c4dfea39ef2093f3a0423200bed6a&query=$location')); print(_response.body); final _bodyJson = jsonDecode(_response.body) as Map<String, dynamic>; final _weatherResponse = WeatherResponse.fromJson(_bodyJson); print(_weatherResponse.current?.temperature); // 正确输出温度 return _weatherResponse.current!; }
记得运行flutter pub run build_runner build生成对应的.g.dart文件。
内容的提问来源于stack exchange,提问作者faiz
相关产品推荐
相关产品推荐

