首页 » PHP教程 » flutterphpjson技巧_在Flutter中解析复杂的JSON

flutterphpjson技巧_在Flutter中解析复杂的JSON

访客 2024-12-07 0

扫一扫用手机浏览

文章目录 [+]

我不得不承认,在Flutter / Dart中利用JSON后,我错过了Android 的gson 天下。
当我开始利用Flutter中的API时,JSON解析确实让我很烦恼。
而且我确定,它让很多初学者感到困惑。

我们将利用dart:convert的内置库。
这是最基本的解析方法,只有在您开始利用Flutter或者您正在构建一个小项目时才建议利用它。
然而,理解Flutter中JSON解析的根本知识非常主要。
当你善于这个,或者你须要利用更大的项目时,可以考虑像json_serializable等代码天生器库。
如果可能的话,我将在往后的文章中先容它们。

flutterphpjson技巧_在Flutter中解析复杂的JSON

示例项目。
它包含您可以试验的本文的所有代码。

flutterphpjson技巧_在Flutter中解析复杂的JSON
(图片来自网络侵删)

JSON构造#1:大略的舆图

让我们从student.json的大略JSON构造开始

{ \公众id\公众:\公众487349\公众, \"大众name\公众:\"大众Pooja Bhaumik\"大众, \"大众score\公众 : 1000}

规则#1: 确定构造。
Json字符串将具有Map(键值对)或List of Maps。

规则#2:用花括号开始?这是Map。

用方括号开始?这是List of Map。

student.json显然是Map。
(例如,id是一个Key,487349是id的值)

让我们为这个json构造制作一个PODO(Plain Old Dart Object?)文件。
您可以在示例项目的[student_model.dart]

class Student{ String studentId; String studentName; int studentScores; Student({ this.studentId, this.studentName, this.studentScores });}

好了!

由于json映射和此PODO文件之间没有映射。
乃至实体名称也不匹配。
这个我知道。
我们还没有完成。
我们必须将这些类成员映射到json工具。
为此,我们须要创建一个factory方法。
根据Dart文档,我们factory在实现布局函数时利用关键字,该布局函数并不总是创建其类的新实例,而这正是我们现在所须要的。

factory Student.fromJson(Map<String, dynamic> parsedJson){ return Student( studentId: parsedJson['id'], studentName : parsedJson['name'], studentScores : parsedJson ['score'] ); }

在这里,我们创建一个名为factory的工厂方法,Student.fromJson其目的是大略地反序列化你的json。

我是一个小菜鸟,你能见告我关于反序列化的事吗?

当然。
我们首先见告您序列化和反序列化。
序列化只是意味着将数据(可能在工具中)写为字符串,而反序列化则与此相反。
它获取原始数据并重修工具模型。
在本文中,我们紧张谈论反序列化部分。
在第一部分中,我们将json字符串反序列化student.json

因此我们的工厂方法可以称为我们的转换器方法。

还必须把稳fromJson方法中的参数。
这是一个Map<String, dynamic>意味着它用一个值映射一个String 键。
这正是我们须要识别构造的缘故原由。
如果这个json构造是一个映射列表,那么这个参数会有所不同。
dynamic

但为何(dynamic)动态?让我们先看看另一个json构造来回答你的问题。

name是Map <String,String>,majors是String和List <String> subjects的Map,是String和List <Object>的Map

由于key始终为 string且值可以是任何类型,因此我们将其保持为dynamic安全。

检讨完全代码student_model.dart 在这里。

访问工具

让我们编写student_services.dart哪些代码可以调用Student.fromJson并从Student工具中检索值。

imports

import 'dart:async' show Future;import 'package:flutter/services.dart' show rootBundle;import 'dart:convert';import 'package:flutter_json/student_model.dart';

末了一个导入是你的模型文件。

加载Json Asset(可选)

Future<String> _loadAStudentAsset() async { return await rootBundle.loadString('assets/student.json');}

在这个的项目中,我们将json文件放在assets文件夹中,因此我们必须以这种办法加载json。
但是,如果您在云上拥有json文件,则可以进行通过网络读取。
网络调用超出了本文的范围,这里不作先容。

加载

Future loadStudent() async { String jsonString = await _loadAStudentAsset(); final jsonResponse = json.decode(jsonString); Student student = new Student.fromJson(jsonResponse); print(student.studentScores);}

在此loadStudent()方法中,

第1行 :从Asset中加载原始json String。

第2行 :解码我们得到的这个原始json字符串。

第3行 :现在我们通过调用Student.fromJson方法对解码的json相应进行反序列化,以便我们现在可以利用Studentobject来访问我们的实体。

第4行 :就像我们在这里做的那样,我们studentScores从Student实例上打印出来。

检讨Flutter掌握台查看所有打印值。
(在Android Studio中,在“运行”Tab页面)

瞧!
您刚刚进行了第一次JSON解析。

把稳:请记住这里的3个片段,我们将利用它进行下一组json解析(仅变动文件名和方法名称),我不会在这里再次重复代码。
但无论如何,您可以在示例项目中找到所有内容。

JSON构造#2:具有数组的大略构造

现在我们征服一个类似于上面的json构造,但它不仅仅是单个值,它也可能有一个值数组。

{ \公众city\"大众: \"大众Mumbai\公众, \公众streets\公众: [ \"大众address1\"大众, \"大众address2\"大众 ]}

以是在这个address.json中,我们有一个city实体,它有一个大略的String值,但是streets是一个数组String。

据我所知,Dart没有数组数据类型,而是有一个List <datatype>以是这里streets将是一个List<String>。

现在我们必须检讨规则#1和规则#2 。
这绝对是Map,由于这是从花括号开始的。
streets仍旧是一个List,但我们稍后会进行谈论。

以是address_model.dart最初看起来会像这样

class Address { final String city; final List<String> streets; Address({ this.city, this.streets });}

既然这是Map,我们的Address.fromJson方法仍旧会有一个Map<String, dynamic>参数。

factory Address.fromJson(Map<String, dynamic> parsedJson) { return new Address( city: parsedJson['city'], streets: parsedJson['streets'], );}

现在address_services.dart通过添加我们上面提到的3个片段来构建。
必须记住放入精确的文件名和方法名。
示例项目已经
address_services.dart为您构建。

现在当你运行它时,你会得到一个小缺点。

type 'List<dynamic>' is not a subtype of type 'List<String>'

我见告你,这些缺点险些涌如今我与Dart开拓的每一步中。
你也会碰着。
那么让我阐明一下这意味着什么。
我们正在申请,List<String>但我们正在List<dynamic>申请,由于我们的申请尚无法确定类型。

以是我们必须明确地将其转换为 List<String>

var streetsFromJson = parsedJson['streets'];List<String> streetsList = new List<String>.from(streetsFromJson);

在这里,首先我们将变量映射streetsFromJson到streets实体。
streetsFromJson还是一个List<dynamic>。
现在,我们明确地创建一个新的List<String> streetsList包含所有元素的streetsFromJson。

在此处查看更新的方法。
现在把稳return语句。

现在你可以运行它,address_services.dart这将完美地运行。

Json构造#3:大略的嵌套构造

现在如果我们有一个像shape.json这样的嵌套构造

{ \公众shape_name\公众:\"大众rectangle\"大众, \"大众property\"大众:{ \"大众width\"大众:5.0, \"大众breadth\"大众:10.0 }}

这里,property包含一个工具而不是一个基本的原始数据类型。

那么PODO将会如何?

好吧,让我们分解一下。

在我们shape_model.dart 的类中,让我们定义一个Property得类。

class Property{ double width; double breadth; Property({ this.width, this.breadth});}

现在让我们构建一个类Shape。
我将这两个类保存在同一个Dart文件中。

class Shape{ String shapeName; Property property; Shape({ this.shapeName, this.property });}

把稳第二个数据成员property基本上是我们上一个类的工具Property。

规则#3:对付嵌套构造,首先创建类和布局函数,然后从底层添加工厂方法。

从底层来看,我们的意思是,首先我们解析Property类,然后我们进入Shape这一级。
这只是我的建议,而不是Flutter规则。

factory Property.fromJson(Map<String, dynamic> json){ return Property( width: json['width'], breadth: json['breadth'] );}

这是一个大略map。

但对付我们在Shape类的工厂方法,我们不能这样做。

factory Shape.fromJson(Map<String, dynamic> parsedJson){ return Shape( shapeName: parsedJson['shape_name'], property : parsedJson['property'] );}

property : parsedJson['property'] 首先,这将抛出类型不匹配缺点 -

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

第二,我们刚刚为Property制作了这个俊秀的小类,我没有看到它在任何地方利用。

对。
我们必须在这里映射我们的Property类。

factory Shape.fromJson(Map<String, dynamic> parsedJson){ return Shape( shapeName: parsedJson['shape_name'], property: Property.fromJson(parsedJson['property']) );}

以是基本上,我们Property.fromJson从我们的Property类中调用方法,无论我们得到什么,我们都将它映射到property实体。
大略!
在这里查看代码。

shape_services.dart和你一起跑吧,你很高兴。

JSON构造#4:带有列表的嵌套构造

我们来看看我们的product.json

{ \"大众id\"大众:1, \"大众name\"大众:\"大众ProductName\公众, \公众images\"大众:[ { \"大众id\"大众:11, \"大众imageName\公众:\"大众xCh-rhy\"大众 }, { \"大众id\"大众:31, \"大众imageName\"大众:\公众fjs-eun\"大众 } ]}

好的,现在我们越来越深入了。
我在里面看到了一个工具列表。

是的,以是这个构造有一个工具列表,但它本身仍旧是一个Map。
(拜会规则#1和规则#2)。
现在参考规则#3,让我们构建我们的product_model.dart。

以是我们创建了两个新类Product和Image。

把稳:Product将有一个List ofImage

class Product { final int id; final String name; final List<Image> images; Product({this.id, this.name, this.images});}class Image { final int imageId; final String imageName; Image({this.imageId, this.imageName});}

工厂方法Image非常大略和基本。

factory Image.fromJson(Map<String, dynamic> parsedJson){ return Image( imageId:parsedJson['id'], imageName:parsedJson['imageName'] );}

现在为工厂实现方法 Product

factory Product.fromJson(Map<String, dynamic> parsedJson){ return Product( id: parsedJson['id'], name: parsedJson['name'], images: parsedJson['images'] );}

这显然会引发运行时缺点

type 'List<dynamic>' is not a subtype of type 'List<Image>'

如果我们这样做,

images: Image.fromJson(parsedJson['images'])

这也是绝对缺点的,它会立即引发缺点,由于你无法将Image工具分配给aList<Image>

以是我们必须创建一个List<Image>然后分配给它images

var list = parsedJson['images'] as List;print(list.runtimeType); //returns List<dynamic>List<Image> imagesList = list.map((i) => Image.fromJson(i)).toList();

list是List <dynamic>。
现在,我们遍历列表,并在每个工具映射list到Image调用Image.fromJson,然后我们把每个舆图工具与一个新的列表toList()并将其存储在List<Image> imagesList。
在这里找到完全的代码。

JSON构造#5:舆图列表

现在让我们来看看photo.json

[ { \公众albumId\"大众: 1, \公众id\公众: 1, \"大众title\公众: \"大众accusamus beatae ad facilis cum similique qui sunt\公众, \公众url\"大众: \公众http://placehold.it/600/92c952\"大众, \"大众thumbnailUrl\"大众: \"大众http://placehold.it/150/92c952\"大众 }, { \公众albumId\"大众: 1, \"大众id\"大众: 2, \"大众title\"大众: \公众reprehenderit est deserunt velit ipsam\"大众, \"大众url\"大众: \"大众http://placehold.it/600/771796\公众, \"大众thumbnailUrl\"大众: \"大众http://placehold.it/150/771796\公众 }, { \"大众albumId\"大众: 1, \"大众id\"大众: 3, \"大众title\公众: \公众officia porro iure quia iusto qui ipsa ut modi\"大众, \"大众url\公众: \公众http://placehold.it/600/24f355\公众, \"大众thumbnailUrl\"大众: \"大众http://placehold.it/150/24f355\公众 }]

哦,哦。
规则#1和规则#2见告我这不能是一个映射,由于json字符串以方括号开头。
那么这是一个工具列表?是。
这里的工具是Photo(或者你想称之为的任何东西)。

class Photo{ final String id; final String title; final String url; Photo({ this.id, this.url, this.title}) ; factory Photo.fromJson(Map<String, dynamic> json){ return new Photo( id: json['id'].toString(), title: json['title'], url: json['json'], ); }}

但它的列表Photo ,这是否意味着你必须建立一个包含?的类List<Photo>

是的,我会建议。

class PhotosList { final List<Photo> photos; PhotosList({ this.photos, });}

另请把稳,此json字符串是一个映射列表。
以是,在我们的工厂方法中,我们没有Map<String, dynamic>参数,由于它是一个List。
这便是为什么首先确定构造很主要的缘故原由。
以是我们的新参数将是一个List<dynamic>。

factory PhotosList.fromJson(List<dynamic> parsedJson) { List<Photo> photos = new List<Photo>(); return new PhotosList( photos: photos, ); }

这会引发缺点

Invalid value: Valid value range is empty: 0

由于我们永久不会利用这种Photo.fromJson方法。

如果我们在列表初始化之后添加这行代码怎么办?

photos = parsedJson.map((i)=>Photo.fromJson(i)).toList();

与之前相同的观点,我们不必将其映射到json字符串中的任何键,由于它是List而不是map。
代码在这里。

JSON构造#6:繁芜的嵌套构造

这是page.json。

我会哀求你办理这个问题。
它已包含在示例项目中。
您只需为此构建模型和做事文件。
但是在给你提示和提示之前我不会总结(如果是的话,你须要任何提示)。

常日适用规则#1和规则#2。
首先确定构造。
这是Map。
以是1-5的所有json构造都会有所帮助。

规则#3哀求您首先创建类和布局函数,然后从底层添加工厂方法。
只是另一个提示。
还要从深层/底层添加类。
例如,对付这个JSON构造,使类Image,然后再Data和Author再主类Page。
并以相同的顺序添加工厂方法。

对付类而言Image,Data请参考Json构造#4。

对付类,Author请参阅Json构造#3

初学者提示:在考试测验任何新Asset时,请记住在pubspec.yaml文件中声明它。

译:https://medium.com/flutter-community/parsing-complex-json-in-flutter-747c46655f51

标签:

相关文章

红帽启动php技巧_红帽LinuxRHCE90课程介绍

红帽是首个(也是环球最大、环球领先)的企业开源软件办理方案供应商,在过去 20 几年里,红帽已经成为开源社区里令人尊敬的成员,资助...

PHP教程 2024-12-09 阅读0 评论0

php不消const技巧_PHP 运用类

类是变量与浸染于这些变量的函数的凑集。工具:实际存在该类事物中每个实物的个体。$a =new User( ; 实例化后的$a。创建...

PHP教程 2024-12-09 阅读0 评论0