在开发应用程序的过程里,我们通常会定义 Model
的类别用来处理资料结构或是资料储存上的使用。
举个简单的例子,定义一个 JSON { "name": "Leo" }
资料的 Model 类别
class User {
User({
required this.name,
});
final String name;
factory User.fromJson(Map<String, dynamic> json) => User(
name: json["name"],
);
Map<String, dynamic> toJson() => {
"name": name,
};
}
void main() {
var userData = { "name": "Leo" };
var user = User.fromJson(userData);
print(user.toJson().toString()); // {name: Leo}
}
资料的安全性:在开发的过程我们虽然也可以从 Map 型别取资料,但是无法掌握 value 对应的真实型别
资料的管理与维护:随着专案大小,定义清楚的 Model 类别有助於开发与维护的工作进行
我们来看看气象资料开放平台 API 回传的 json 资料结构大致如下,可以看到我们我们至少就有5层的 Model 需要定义
{
"success": "true",
"records": {
"locations": [{
"datasetDescription": "台湾各县市乡镇未来3天(72小时)逐3小时天气预报",
"locationsName": "台北市",
"dataid": "D0047-061",
"location": [{
"locationName": "中正区",
"geocode": "63000050",
"lat": "25.046058",
"lon": "121.516565",
"weatherElement": [{
"elementName": "Wx",
"description": "天气现象",
"time": [{
"startTime": "2021-09-16 06:00:00",
"endTime": "2021-09-16 09:00:00",
"elementValue": [{
"value": "短暂阵雨或雷雨",
"measures": "自定义 Wx 文字"
},
{
"value": "15",
"measures": "自定义 Wx 单位"
}
]
}]
}]
}]
}]
}
}
这个 API 回传的资料结构包含了某地区、某时间、某天气因子、某单位…,在取用资料上相对麻烦,
我们可以透过 Model 类别来处理回传的资料格式,并定义一些方法来取得资料内容,如下:
var data = await WetherAPI().fetch(service, parameters: params);
// json_serializable
var weather = WeatherModel.fromJson(data);
// first 自定义属性用来取得第一笔
var record = weather.records.first;
// 自定义 element 方法用来取得天气因子
var description = record.element("WeatherDescription").now.values[0].value;
var wx = record.element("Wx").now.values[1].value;
简单的资料结构我们可以手动写 Code 处理,不过实务上的资料结构通常比较复杂,我们可以使用一些工具协助创建 Model 类别,将开发时间留给业务逻辑的处理而不是资料的建模。
json_serializable - 需手动定义好资料的结构,可以自动产生序列化相关的程序码。
quicktype - 提供 json 的资料内容,会自动化产生 Model 的程序码,需检查上下内容是否符合自己预期。
透过自动化的转换,我们使用 quicktype
提供 json 格式自动化产生对应的 Model
完整程序码如下:
// To parse this JSON data, do
//
// final weatherApiResponse = weatherApiResponseFromJson(jsonString);
import 'package:meta/meta.dart';
import 'dart:convert';
WeatherApiResponse weatherApiResponseFromJson(String str) => WeatherApiResponse.fromJson(json.decode(str));
String weatherApiResponseToJson(WeatherApiResponse data) => json.encode(data.toJson());
class WeatherApiResponse {
WeatherApiResponse({
required this.success,
required this.records,
});
final String success;
final Records records;
factory WeatherApiResponse.fromJson(Map<String, dynamic> json) => WeatherApiResponse(
success: json["success"],
records: Records.fromJson(json["records"]),
);
Map<String, dynamic> toJson() => {
"success": success,
"records": records.toJson(),
};
}
class Records {
Records({
required this.locations,
});
final List<RecordsLocation> locations;
factory Records.fromJson(Map<String, dynamic> json) => Records(
locations: List<RecordsLocation>.from(json["locations"].map((x) => RecordsLocation.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"locations": List<dynamic>.from(locations.map((x) => x.toJson())),
};
}
class RecordsLocation {
RecordsLocation({
required this.datasetDescription,
required this.locationsName,
required this.dataid,
required this.location,
});
final String datasetDescription;
final String locationsName;
final String dataid;
final List<LocationLocation> location;
factory RecordsLocation.fromJson(Map<String, dynamic> json) => RecordsLocation(
datasetDescription: json["datasetDescription"],
locationsName: json["locationsName"],
dataid: json["dataid"],
location: List<LocationLocation>.from(json["location"].map((x) => LocationLocation.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"datasetDescription": datasetDescription,
"locationsName": locationsName,
"dataid": dataid,
"location": List<dynamic>.from(location.map((x) => x.toJson())),
};
}
class LocationLocation {
LocationLocation({
required this.locationName,
required this.geocode,
required this.lat,
required this.lon,
required this.weatherElement,
});
final String locationName;
final String geocode;
final String lat;
final String lon;
final List<WeatherElement> weatherElement;
factory LocationLocation.fromJson(Map<String, dynamic> json) => LocationLocation(
locationName: json["locationName"],
geocode: json["geocode"],
lat: json["lat"],
lon: json["lon"],
weatherElement: List<WeatherElement>.from(json["weatherElement"].map((x) => WeatherElement.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"locationName": locationName,
"geocode": geocode,
"lat": lat,
"lon": lon,
"weatherElement": List<dynamic>.from(weatherElement.map((x) => x.toJson())),
};
}
class WeatherElement {
WeatherElement({
required this.elementName,
required this.description,
required this.time,
});
final String elementName;
final String description;
final List<Time> time;
factory WeatherElement.fromJson(Map<String, dynamic> json) => WeatherElement(
elementName: json["elementName"],
description: json["description"],
time: List<Time>.from(json["time"].map((x) => Time.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"elementName": elementName,
"description": description,
"time": List<dynamic>.from(time.map((x) => x.toJson())),
};
}
class Time {
Time({
required this.startTime,
required this.endTime,
required this.elementValue,
});
final DateTime startTime;
final DateTime endTime;
final List<ElementValue> elementValue;
factory Time.fromJson(Map<String, dynamic> json) => Time(
startTime: DateTime.parse(json["startTime"]),
endTime: DateTime.parse(json["endTime"]),
elementValue: List<ElementValue>.from(json["elementValue"].map((x) => ElementValue.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"startTime": startTime.toIso8601String(),
"endTime": endTime.toIso8601String(),
"elementValue": List<dynamic>.from(elementValue.map((x) => x.toJson())),
};
}
class ElementValue {
ElementValue({
required this.value,
required this.measures,
});
final String value;
final String measures;
factory ElementValue.fromJson(Map<String, dynamic> json) => ElementValue(
value: json["value"],
measures: json["measures"],
);
Map<String, dynamic> toJson() => {
"value": value,
"measures": measures,
};
}
>>: Kotlin Android 第25天,从 0 到 ML - TensorFlow Lite 功能与特色
完成付款请求之後,接下来是准备好接收金流商回传资讯的 Response 类别,目前外挂的资料夹结构如...
如同Day 2提到的角落生物,俗称隐私服务三宝之称的服务条款(Term of use/Term of...
将几篇 Boxenn 相关文章整理成分类目录(范例 GitHub repository 建置中,完成...
VS CODE安装好之後,就可以来认识HTML啦~ 开始写HTML前的步骤 首先,在桌面上新增一个资...
今天刚好找到一个有趣的文字识别模型,想来和大家介绍一下~ PaddleOCR PaddleOCR是百...