Contents

Fetch data dynamically

What's the point?

  • 网络上的数据通常采用JSON格式.
  • JSON是基于文本的并且易于阅读.
  • dart:convert库提供了对JSON的支持.
  • 使用HttpRequest动态加载数据.

Web应用程序通常使用JSON (JavaScript对象表示法)在客户端和服务器之间传递数据. 数据可以序列化为JSON字符串,然后在客户端和服务器之间传递,并在目标位置作为对象恢复. 本教程向您展示如何使用dart:convert库中的函数来生成和使用JSON数据. 由于JSON数据通常是动态加载的,因此本教程还介绍了Web应用程序如何使用HTTP请求从HTTP服务器获取数据. 对于Web应用程序,HTTP请求由运行该应用程序的浏览器提供服务,因此受到浏览器安全性的限制.

About JSON

JSON数据格式很轻便且基于文本,因此人类易于读写. 使用JSON,可以序列化各种数据类型和简单的数据结构(例如列表和映射),并用字符串表示.

尝试一下! 以下应用程序its_all_about_you显示各种类型的数据的JSON字符串. 单击运行以启动应用程序. 然后更改输入元素的值,并检查每种数据类型的JSON格式. 您可能希望在DartPad中打开该应用程序,以便为该应用程序的代码和UI提供更多空间.

dart:convert库包含两个用于处理JSON字符串的便捷函数:

dart:convert function Description
json.decode() 从包含JSON数据的字符串构建Dart对象.
json.encode() 将Dart对象序列化为JSON字符串.

要使用这些功能,您需要将dart:convert导入Dart代码:

import 'dart:convert';

json.encode()json.decode()函数可以自动处理以下Dart类型:

  • num
  • String
  • bool
  • Null
  • List
  • Map

Serializing data into JSON

使用json.encode()函数序列化支持JSON的对象. 该showJson()函数将所有数据转换为JSON字符串.

void showJson(Event _) {
  // Grab the data that will be converted to JSON.
  final favNum = int.tryParse(favoriteNumber.value);
  final pi = double.tryParse(valueOfPi.value);
  final chocolate = loveChocolate.checked;
  final sign = horoscope.value;
  final favoriteThings = <String>[
    favOne.value,
    favTwo.value,
    favThree.value,
  ];

  final formData = {
    'favoriteNumber': favNum,
    'valueOfPi': pi,
    'chocolate': chocolate,
    'horoscope': sign,
    'favoriteThings': favoriteThings
  };

  // Convert to JSON and display results.
  intAsJson.text = json.encode(favNum);
  doubleAsJson.text = json.encode(pi);
  boolAsJson.text = json.encode(chocolate);
  stringAsJson.text = json.encode(sign);
  listAsJson.text = json.encode(favoriteThings);
  mapAsJson.text = json.encode(formData);
}

下面显示的是使用应用程序中的原始值由代码产生的JSON字符串:

The JSON string for the its_all_about_you app

  • 如果数字和布尔值是代码中的文字值,则没有引号或其他勾号,它们的显示方式与之相同.
  • 布尔值是truefalse .
  • 值表示为null .
  • 字符串包含在引号中.
  • 列表用方括号划出; 它的项目以逗号分隔. 此示例中的列表包含字符串.
  • 地图用花括号划出; 它包含逗号分隔的键/值对,其中键首先出现,然后是冒号,然后是值. 在此示例中,映射中的键是字符串. 映射中的值的类型不同,但是它们都是JSON可解析的.

Parsing JSON data

使用dart:convert库中的json.decode()函数从JSON字符串创建Dart对象. 该示例最初从此JSON字符串填充表单中的值:

final jsonDataAsString = '''{
  "favoriteNumber": 73,
  "valueOfPi": 3.141592,
  "chocolate": true,
  "horoscope": "Cancer",
  "favoriteThings": ["monkeys", "parrots", "lattes"]
}''';

Map jsonData = json.decode(jsonDataAsString) as Map;

此代码使用格式正确的JSON字符串调用json.decode() .

在此示例中,完整的JSON字符串被硬编码到Dart代码中,但是它可以由表单本身创建,也可以从静态文件中读取,也可以从服务器中获取. 此页面后面的示例显示如何从与应用程序代码位于同一位置的文件中动态获取JSON数据.

json.decode()函数读取字符串并从中构建Dart对象. 在此示例中, json.decode()函数基于JSON字符串中的信息创建Map对象. Map包含各种类型的对象,包括整数,双精度型,布尔值,常规字符串和列表. 映射中的所有键都是字符串.

About URIs and HTTP requests

要从Web应用程序内发出HTTP GET请求,您需要提供资源的URI(统一资源标识符). URI是唯一命名资源的字符串. URL(统一资源定位符)是一种特定的URI,它也提供资源的位置. 万维网上的资源URL包含三部分信息:

  • 用于通讯的协议
  • 服务器的主机名
  • 资源的路径

For example, the URL for this page breaks down as follows:

The tutorial URL

该URL指定HTTP协议. 当您在Web浏览器中输入HTTP地址时,浏览器将HTTP GET请求发送到Web服务器,然后Web服务器将发送包含页面内容(或错误消息)的HTTP响应.

Basic HTTP communication between client and server

Web浏览器中的大多数HTTP请求都是简单的GET请求,用于请求页面内容. 但是,HTTP协议允许其他类型的请求,例如用于从客户端发送数据的POST.

在浏览器内部运行的Dart网络应用可以发出HTTP请求. 这些HTTP请求由运行该应用的浏览器处理. 即使浏览器本身可以在Web上的任何位置发出HTTP请求,但由于安全性限制,在浏览器中运行的Dart Web应用程序只能发出有限的 HTTP请求. 实际上,由于这些限制,来自Web应用程序的HTTP请求主要用于检索特定于该应用程序并与该应用程序位于同一位置的文件中的信息.

SDK提供了以下有用的类,用于制定URI和发出HTTP请求:

飞镖代码 Library Description
Uri dart:core 统一资源标识符
HttpRequest dart:html 客户端HTTP请求对象. 用于Web应用程序.
HttpRequest dart:io 服务器端HTTP请求对象. 在Web应用程序中不起作用.

Using getString() to load a file

您的Web应用程序可以发出的一个有用的HTTP请求是对来自与该应用程序相同来源的数据文件的GET请求. 下面的示例读取一个名为portmanteaux.json的数据文件,其中包含JSON格式的单词列表. 当您单击按钮时,该应用会向服务器发出GET请求并加载文件.

尝试一下! 单击运行 ,然后单击获取portmanteaux按钮.

该程序使用HttpRequest类提供的便捷方法getString()从服务器请求文件.

Future<void> makeRequest(Event _) async {
  const path = 'https://dart.dev/f/portmanteaux.json';
  try {
    // Make the GET request
    final jsonString = await HttpRequest.getString(path);
    // The request succeeded. Process the JSON.
    processResponse(jsonString);
  } catch (e) {
    // The GET request failed. Handle the error.
    // ···
  }
}

void processResponse(String jsonString) {
  for (final portmanteau in json.decode(jsonString)) {
    wordList.children.add(LIElement()..text = portmanteau as String);
  }
}

getString()方法使用Future对象来处理请求. Future是一种异步执行可能耗时的操作(例如HTTP请求)的方法. 如果您还没有遇到过期货,则可以在异步编程代码实验室中了解有关期货以及asyncawait关键字的信息. 在此之前,您可以使用上面的代码作为指南,并为processResponse()函数的主体提供自己的代码,并为处理错误提供自己的代码.

Using an HttpRequest object to load a file

getString()方法适用于HTTP GET请求,该请求返回从资源加载的字符串. 对于其他情况,您需要创建一个HttpRequest对象,配置其标头和其他信息,然后使用send()方法发出请求.

本节重写portmanteaux代码以显式构造HttpRequest对象.

Setting up the HttpRequest object

该按钮的鼠标单击处理程序将创建一个HttpRequest对象,使用URI和回调函数对其进行配置,然后发送该请求. 让我们看一下Dart代码:

Future<void> makeRequest(Event _) async {
  const path = 'https://dart.dev/f/portmanteaux.json';
  final httpRequest = HttpRequest();
  httpRequest
    ..open('GET', path)
    ..onLoadEnd.listen((e) => requestComplete(httpRequest))
    ..send('');
}

Making an HTTP GET request

Sending the request

send()方法将请求发送到服务器.

httpRequest.send('');

因为此示例中的请求是一个简单的GET请求,所以代码可以发送一个空字符串. 对于其他类型的请求,例如POST请求,此字符串可以包含相关数据. 您还可以通过使用setRequestHeader()方法设置各种头参数来配置HttpRequest对象.

Handling the response

要处理HTTP响应,您需要在调用send()之前设置一个回调函数. 我们的示例为onLoadEnd事件设置了单行回调函数, 事件进而调用requestComplete() . 请求成功完成或未成功完成时,都会调用此回调函数.

Set up a callback function for request completion

requestComplete()函数检查请求的状态码.

void requestComplete(HttpRequest request) {
  switch (request.status) {
    case 200:
      processResponse(request.responseText);
      return;
    default:
      // The GET request failed. Handle the error.
      // ···
  }
}

如果状态码为200,则找到文件并成功加载. 请求的文件( portmanteaux.json )的内容在HttpRequest对象的responseText属性中返回.

Populating the UI from JSON

portmanteaux示例中的数据文件portmanteaux.json包含以下JSON格式的字符串列表:

[
  "portmanteau", "fantabulous", "spork", "smog",
  "spanglish", "gerrymander", "turducken", "stagflation",
  "bromance", "freeware", "oxbridge", "palimony", "netiquette",
  "brunch", "blog", "chortle", "Hassenpfeffer", "Schnitzelbank"
]

根据请求,服务器读取文件并将其作为单个字符串发送到客户端程序.

使用json.decode() ,该应用程序可以轻松地将JSON格式的单词列表转换为Dart字符串列表,为每个单词创建一个新的LIElement并将其添加到页面上的<ul>元素中.

void processResponse(String jsonString) {
  for (final portmanteau in json.decode(jsonString)) {
    wordList.children.add(LIElement()..text = portmanteau as String);
  }
}

Other resources

by  ICOPY.SITE