Nowadays It is very rare for a mobile to work only in offline mode and never communicate with any server and submit or get response from server and show it to app users.
So If your Application needs to communicate with server or needs to consume any third party API you will need to interact with JSON.
Because nowadays JSON (JAVA SCRIPT OBJECT NOTATION) is very common data format.
Typically there are two methods through which you can parse JSON Objects in your application.
Manually parsing JSON is error prone and time taking task.
Because you have to write code for getting each and every Map<String, dynamic> manually.
And if at run-time any of the key or value is missing in JSON Object your app might crash.
I assume you know JSON Data Format (It is in key value pair, whereas Key is always string and value can be anything. Value can be another JSON Object, JSON Array, String, Float, Double that is why It is dynamic in Flutter).
If your app needs to use third party libraries or SDK for example Firebase SDK, http (for network communication) you are required to add packages in your flutter app.
Please see the highlighted fields, Flutter packages can be added under pubspec.yaml file in your project.
Any package will be under dependencies block like above http package.
After you make any change in pubspec.yaml file or add any new package just click Packages get button on top right (Highligted).
Now are are ready to make network request or API call and Parse JSON.
// pubspec.yaml name: flutter_json_parsing_example description: Flutter JSON Parsing Example Code DART version: 1.0.0+1 environment: sdk: ">=2.0.0-dev.68.0 <3.0.0" dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 shrine_images: 1.0.0 http: ^0.11.3+16 dev_dependencies: flutter_test: sdk: flutter # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec # The following section is specific to Flutter. flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true
We will be calling Youtube Search API in our Flutter app and will parse its response.
API End Point:
https://www.googleapis.com/youtube/v3/search?q=javascript&maxResults=12&part=snippet&key=AIzaSyCk3nUhQgjVI9zKjMmuNaF6sxCY4
Simply hit this API in your browser and you will get JSON response.
Note: You are supposed to use your own Youtube API Key and replace it with key attribute.
I have selected complex JSON Object for Parsing tutorial so we can cover all use cases related to JSON Parsing in Flutter e.g Serialization, Array Parsing, Nested Objects and all that.
As you can see above JSON Object contains pageInfo Object and items Array and items array contains few other JSON Objects like id and snippet.
Snippet Object further contains Video Title, Video Description and thumbnails.
Here we will perform two main functions.
You need to import Future and http Packages in this class.
import 'package:http/http.dart' as http; import 'dart:async' show Future; var apiURL = "https://www.googleapis.com/youtube/v3/search?q=Android&maxResults=12 &part=snippet &key=YOUR_YOUTUBE_API_KEY"; Future<http.Response> searchYoutube() async { final youtubeResponse = http.Client().get(apiURL); }
Lets understand keywords used in above Network Utility class.
Future is a Dart class which is used to work with asynchronus operation. It is used to represent a value or object which will be available at later.
http Response will contain Raw data returned from API Call.
Later we will convert/map this response into Dart Model Classes.
Building Http object for making Network Call.
At this stage we are making youtube search api call with ‘Android’ search Query.
And getting http Response object.
But we need to parse http Response object into Dart Model Classes.
Create a new package ‘model’ in your project and create new Dart Class YoutubeResponse.
// YoutubeResponse.dart import 'pageInfo.dart'; import 'Item.dart'; class YoutubeResponse { // Fields and Objects in YoutubeResponse according to JSON Data. String kind; String etag; String nextPageToken; String regionCode; pageInfo mPageInfo; List<Item> items; // Constructor YoutubeResponse( {this.kind, this.etag, this.nextPageToken, this.regionCode, this.mPageInfo, this.items}); // toJson() function discussed below. Map<String, dynamic> toJson() => { 'kind': kind, 'etag': etag, 'nextPageToken': nextPageToken, 'regionCode': regionCode, 'pageInfo': mPageInfo, 'items': items, }; // fromJSON FUNCTION EXPLAINED BELOW. factory YoutubeResponse.fromJSON(Map<String, dynamic> YoutubeResponseJson) { var list = YoutubeResponseJson['items'] as List; List<Item> itemsList = list.map((i) => Item.fromJSON(i)).toList(); return new YoutubeResponse( kind: YoutubeResponseJson['kind'], etag: YoutubeResponseJson['etag'], nextPageToken: YoutubeResponseJson['nextPageToken'], regionCode: YoutubeResponseJson['regionCode'], mPageInfo: pageInfo.fromJSON(YoutubeResponseJson['pageInfo']), items: itemsList); } }
Above fromJSON function/method starts with ‘factory‘ keyword.
In our YoutubeResponse.fromJson() function we are just deserializing our JSON Object and returning a new Instance of YoutubeResponse.dart class.
As you can see that fromJson function receives Map<String, dynamic> object.
“Our JSON is always in key value pair”.
In Map object String represents a “key” and dynamic represents value.
Why Dynamic ?
Because objects inside JSON can be of any type (String, Other Custom Objects).
As you might have noticed that YoutubeResponse contains 4 Strings (Objects in JSON) and 2 Other Model classes (also Objects in returned JSON)
String kind;
String etag;
String nextPageToken;
String regionCode;
Parsing a string object ‘Kind’ is as simple as
kind: YoutubeResponseJson[‘kind’]
pageInfo mPageInfo; // Parsing child JSON objects in Flutter.
List<Item> items; // this one is JSON ARRAY.
Please note that below code snippet is from our YoutubeResponseAPI fromJSON function (inside constructor body).
var list = YoutubeResponseJson['items'] as List; List<Item> itemsList = list.map((i) => Item.fromJSON(i)).toList();
mPageInfo: pageInfo.fromJSON(YoutubeResponseJson['pageInfo'])
Lets create rest of the Model Classes.
Copy paste below classes in your project model package.
import 'dart:convert'; class pageInfo { int totalResults; int resultsPerPage; pageInfo({this.totalResults, this.resultsPerPage}); Map<String, dynamic> toJson() => { 'totalResults': totalResults, 'resultsPerPage': resultsPerPage, }; factory pageInfo.fromJSON(Map<String, dynamic> pageInfoJson) { return new pageInfo( totalResults: pageInfoJson['totalResults'], resultsPerPage: pageInfoJson['resultsPerPage'], ); } }
//////////////////////////////////////////
import 'dart:convert'; import 'package:http/http.dart' as http; import 'Snippet.dart'; import 'Id.dart'; class Item { String kind; String etag; Id id; Snippet snippet; Item({this.kind, this.etag, this.id, this.snippet}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'kind': kind, 'etag': etag, 'id': id, 'snippet': snippet, }; factory Item.fromJSON(Map<String, dynamic> ItemJson) { return Item( kind: ItemJson['kind'], etag: ItemJson['etag'], id: Id.fromJSON(ItemJson['id']), snippet: Snippet.fromJSON(ItemJson['snippet']), ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; import 'Thumbnails.dart'; class Snippet { String publishedAt; String channelId; String title; String description; Thumbnails thumbnails; String channelTitle; String liveBroadcastContent; Snippet( {this.publishedAt, this.channelId, this.title, this.description, this.thumbnails, this.channelTitle, this.liveBroadcastContent}); Map<String, dynamic> toJson() => { 'publishedAt': publishedAt, 'channelId': channelId, 'title': title, 'description': description, 'thumbnails': thumbnails, 'channelTitle': channelTitle, 'liveBroadcastContent': liveBroadcastContent, }; factory Snippet.fromJSON(Map<String, dynamic> SnippetJson) { return Snippet( publishedAt: SnippetJson['publishedAt'], channelId: SnippetJson['channelId'], title: SnippetJson['title'], description: SnippetJson['description'], thumbnails: Thumbnails.fromJSON(SnippetJson['thumbnails']) , channelTitle: SnippetJson['channelTitle'], liveBroadcastContent: SnippetJson['liveBroadcastContent'], ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; import 'Default.dart'; import 'Medium.dart'; import 'High.dart'; class Thumbnails { Default mDefault; Medium medium; High high; Thumbnails({this.mDefault, this.medium, this.high}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'default': mDefault, 'medium': medium, 'high': high, }; factory Thumbnails.fromJSON(Map<String, dynamic> ThumbnailsJson) { return Thumbnails( mDefault: Default.fromJSON(ThumbnailsJson['default']), medium: Medium.fromJSON(ThumbnailsJson['medium']), high: High.fromJSON(ThumbnailsJson['high']), ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; class Id { String kind; String videoId; Id({this.kind, this.videoId}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'kind': kind, 'videoId': videoId, }; factory Id.fromJSON(Map<String, dynamic> defaultJson) { return Id( kind: defaultJson['kind'], videoId: defaultJson['videoId'], ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; class Medium { int height; int width; String url; Medium({this.height, this.width, this.url}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'height': height, 'width': width, 'url': url, }; factory Medium.fromJSON(Map<String, dynamic> MediumJson) { return Medium( height: MediumJson['height'], width: MediumJson['width'], url: MediumJson['url'], ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; class High { int height; int width; String url; High({this.height, this.width, this.url}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'height': height, 'width': width, 'url': url, }; factory High.fromJSON(Map<String, dynamic> HighJson) { return High( height: HighJson['height'], width: HighJson['width'], url: HighJson['url'], ); } }
import 'dart:convert'; import 'package:http/http.dart' as http; class Default { int height; int width; String url; Default({this.height, this.width, this.url}); var data = JsonEncoder().convert(""); Map<String, dynamic> toJson() => { 'height': height, 'width': width, 'url': url, }; factory Default.fromJSON(Map<String, dynamic> defaultJson) { return Default( height: defaultJson['height'], width: defaultJson['width'], url: defaultJson['url'], ); } }
please make sure you have created 9 Model classes.
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:async' show Future; import 'model/YoutubeResponse.dart'; import 'dart:convert'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: new AppBar( title: new Text('Flutter Demo App JSON Parsing'), ), body: Center( child: FutureBuilder<YoutubeResponse>( future: searchYoutubeAPI(), builder: (context, snapshot) { return Text(snapshot.data.etag); }, ), ), ), ); } }
Complete Code:
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:async' show Future; import 'model/YoutubeResponse.dart'; import 'dart:convert'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'Flutter Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: Scaffold( appBar: new AppBar( title: new Text('Flutter Demo App JSON Parsing'), ), body: Center( child: FutureBuilder<YoutubeResponse>( future: searchYoutubeAPI(), builder: (context, snapshot) { return Text(snapshot.data.etag); }, ), ), ), ); } } var apiURL = "https://www.googleapis.com/youtube/v3/search?q=Android&maxResults=12&part=snippet&key=YOUR_API_KEY"; Future<YoutubeResponse> searchYoutubeAPI() async { var youtubeResponse = await http.Client().get(apiURL); var parsedResponse = YoutubeResponse.fromJSON(json.decode(youtubeResponse.body)); return parsedResponse; print(" Youtube JSON PARSING LOG: " + parsedResponse.items[0].data); }
copyright: http://developine.com/