Decode Json from Youtube api on Flutter
Solution 1
Might be bit late to answer the question.
If you want to learn how to parse complex json data use these articles.
1. Parsing JSON in the background - Flutter cookbook
and Parsing complex JSON in Flutter- medium.com by Pooja Bhaumik
FYI - Youtube data api response is in a nested Json format
I used a alternative way, this is not recommended for big applications(I was just playing around with it and this is only for above type json tree)
Use async function to retrieve and parse Json data.
final String dataUrl = "YOUR-JSON-URL";
Future<String> getdet() async {
var response = await http.get(Uri.encodeFull(dataUrl), headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
var responseBody = json.decode(response.body);
convertedData = responseBody["items"];
} else {
throw Exception('Failed to Load Data');
}
"items " is the array starting point
after that you can use it in a Widget for example
Widget recentWidget(){
return ListView.builder(
itemCount: convertedData == null ? 0 : recent.length,
itemBuilder: (BuildContext context, int index, ) {
return Column(
children: <Widget>[
Card(
child: Column(
children: <Widget>[
new Image.network(recent[index]["snippet"]["thumbnails"]["medium"]["url"]),
new ListTile(
title: new Text(recent[index]["snippet"]["title"]),
subtitle: Text("This is Subtitle"),
},
dense: true,
),
],
),
)
],
);
},shrinkWrap: true,
physics: ClampingScrollPhysics(),
)
}
Hope this helps.
Solution 2
What you are trying won't work with Dart, this is not javascript. Dart has very strong type system, which is great. You are trying to assign value to a variable you've defined as String
, but the response you have defined a dynamic, so Dart can't validate the value assignment. Also items is array, there is no such key items->snippet.
The correct way to do this is to create model deinitions, which will handle deserialisation and also will provide convenient way of accessing properties you are interested in.
class YoutubeResponse {
String kind;
String etag;
String nextPageToken;
String regionCode;
List<Item> items;
YoutubeResponse(
{this.kind,
this.etag,
this.nextPageToken,
this.regionCode,
this.items});
Map<String, dynamic> toJson() => {
'kind': kind,
'etag': etag,
'nextPageToken': nextPageToken,
'regionCode': regionCode,
'items': items,
};
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);
}
}
class Item {
String kind;
String etag;
Id id;
Snippet snippet;
Item({this.kind, this.etag, this.id, this.snippet});
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']),
);
}
}
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'],
);
}
}
class Medium {
int height;
int width;
String url;
Medium({this.height, this.width, this.url});
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'],
);
}
}
class High {
int height;
int width;
String url;
High({this.height, this.width, this.url});
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'],
);
}
}
class Default {
int height;
int width;
String url;
Default({this.height, this.width, this.url});
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'],
);
}
}
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']),
);
}
}
Now that we have described the format of the JSON we expect it is very easy to parse it:
YoutubeResponse parsedResponse =
YoutubeResponse.fromJSON(json.decode(response.body));
You can then access the items via parsedResponse.items
, then loop through them and get the title, descriptions etc.
Solution 3
To further the answer by @Shaddy (which works) here is my class that calls the network
class VideoNetwork {
static Future<List<Item>> fetchPost() async {
final response =
await http.get(<URL for Youtube Videos>);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON
return compute(parseVideos, response.body);
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
static List<Item> parseVideos(String responseBody) {
YoutubeResponse response =
YoutubeResponse.fromJSON(json.decode(responseBody));
return response.items.toList();
}
}
Capitan Luzzatto
Updated on December 07, 2022Comments
-
Capitan Luzzatto over 1 year
I make a call to Youtube API and get this Json:
"kind": "youtube#videoListResponse", "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/s7-xmHXpuqQxYzDp_wxhm59K4LE\"", "pageInfo": { "totalResults": 1, "resultsPerPage": 1 }, "items": [ { "kind": "youtube#video", "etag": "\"XI7nbFXulYBIpL0ayR_gDh3eu1k/pajQ7iBy-7A0V_owifxkw-Kbw-Y\"", "id": "7lCDEYXw3mM", "snippet": { "publishedAt": "2012-06-20T23:12:38.000Z", "channelId": "UC_x5XG1OV2P6uZZ5FSM9Ttw", "title": "Google I/O 101: Q&A On Using Google APIs", "description": "Antonio Fuentes speaks to us and takes questions on working with Google APIs and OAuth 2.0.", "thumbnails": { "default": { "url": "https://i.ytimg.com/vi/7lCDEYXw3mM/default.jpg", "width": 120, "height": 90 }, "medium": { "url": "https://i.ytimg.com/vi/7lCDEYXw3mM/mqdefault.jpg", "width": 320, "height": 180 }, "high": { "url": "https://i.ytimg.com/vi/7lCDEYXw3mM/hqdefault.jpg", "width": 480, "height": 360 }
But now I want to parse it and get just 3 nodes:
- Title
- Description
- The url for the default thumbnail
Indeed I get the Json response and can see it on the logs, but when try to parse it every time it fails.
This is my code:
final response = await http.get( 'https://www.googleapis.com/youtube/v3/videos?id=HEREGOESMYAPIKEY&part=snippet&id=T0Jqdjbed40'); final parsed = json.decode(response.body).cast<Map<String, dynamic>>(); String title = parsed['items']['snippet']['title']; print(title); String description = parsed['items']['snippet']['description']; print(description); String thumbnail = parsed['items']['snippet']['thumbnails']['default']['url']; print(thumbnail);
-
Capitan Luzzatto over 5 yearsI added your code but it gives me a [VERBOSE-2:shell.cc(188)] Dart Error: Unhandled exception: NoSuchMethodError: The method 'fromJSON' was called on null.
-
Sh1d0w over 5 years@CapitanLuzzatto Have you created and imported all models?
-
Capitan Luzzatto over 5 yearsYes, also I noted that Android Studio didn't recognized the field Id on the Item object and mPageInfo ond YouTubeResponse object.