Skip to content

Commit dcdceb6

Browse files
committed
Handle empty or missing JSON fields in the iTunes and PodcastIndex search results.
1 parent 9fedfcc commit dcdceb6

File tree

5 files changed

+39
-34
lines changed

5 files changed

+39
-34
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.6.9
2+
3+
- Bug fix: handle empty fields from iTunes and PodcastIndex API call results.
4+
15
## 0.6.8
26

37
- BREAKING CHANGE: Language is now a text parameter (2-3 letter code) rather than enum. This is because iTunes largely ignores language, but PodcastIndex can use it for trending podcasts.

lib/src/model/item.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,11 @@ class Item {
113113
});
114114

115115
/// Takes our json map and builds a Podcast instance from it.
116-
factory Item.fromJson(
117-
{required Map<String, dynamic>? json,
118-
ResultType type = ResultType.itunes}) {
119-
return type == ResultType.itunes
120-
? _fromItunes(json!)
121-
: _fromPodcastIndex(json!);
116+
factory Item.fromJson({
117+
required Map<String, dynamic>? json,
118+
ResultType type = ResultType.itunes,
119+
}) {
120+
return type == ResultType.itunes ? _fromItunes(json!) : _fromPodcastIndex(json!);
122121
}
123122

124123
static Item _fromItunes(Map<String, dynamic> json) {
@@ -143,26 +142,25 @@ class Item {
143142
artworkUrl60: json['artworkUrl60'] as String?,
144143
artworkUrl100: json['artworkUrl100'] as String?,
145144
artworkUrl600: json['artworkUrl600'] as String?,
146-
genre: Item._loadGenres(
147-
json['genreIds'].cast<String>(), json['genres'].cast<String>()),
148-
releaseDate: DateTime.parse(json['releaseDate']),
145+
genre: json['genreIds'] == null
146+
? <Genre>[]
147+
: Item._loadGenres(json['genreIds'].cast<String>(), json['genres'].cast<String>()),
148+
releaseDate: DateTime.tryParse(json['releaseDate'] ?? ''),
149149
country: json['country'] as String?,
150150
primaryGenreName: json['primaryGenreName'] as String?,
151151
contentAdvisoryRating: json['contentAdvisoryRating'] as String?,
152152
);
153153
}
154154

155155
static Item _fromPodcastIndex(Map<String, dynamic> json) {
156-
int pubDateSeconds =
157-
json['lastUpdateTime'] ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;
156+
int pubDateSeconds = json['lastUpdateTime'] ?? DateTime.now().millisecondsSinceEpoch ~/ 1000;
158157

159158
var pubDate = Duration(seconds: pubDateSeconds);
160159
var categories = json['categories'];
161160
var genres = <Genre>[];
162161

163162
if (categories != null) {
164-
categories
165-
.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
163+
categories.forEach((key, value) => genres.add(Genre(int.parse(key), value)));
166164
}
167165

168166
return Item(

lib/src/search/itunes_search.dart

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ final class ITunesSearch extends BaseSearch {
7777
connectTimeout: Duration(milliseconds: timeout),
7878
receiveTimeout: Duration(milliseconds: timeout),
7979
headers: {
80-
'User-Agent': userAgent == null || userAgent.isEmpty
81-
? podcastSearchAgent
82-
: userAgent,
80+
'User-Agent': userAgent == null || userAgent.isEmpty ? podcastSearchAgent : userAgent,
8381
},
8482
),
8583
);
@@ -116,8 +114,7 @@ final class ITunesSearch extends BaseSearch {
116114
setLastError(e);
117115
}
118116

119-
return SearchResult.fromError(
120-
lastError: lastError ?? '', lastErrorType: lastErrorType);
117+
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
121118
}
122119

123120
/// Fetches the list of top podcasts
@@ -153,8 +150,7 @@ final class ITunesSearch extends BaseSearch {
153150
setLastError(e);
154151
}
155152

156-
return SearchResult.fromError(
157-
lastError: lastError ?? '', lastErrorType: lastErrorType);
153+
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
158154
}
159155

160156
@override
@@ -180,8 +176,7 @@ final class ITunesSearch extends BaseSearch {
180176

181177
if (count == 0) {
182178
// ignore: avoid_print
183-
print(
184-
'Warning: Could not find $title via lookup id: $feedApiEndpoint/lookup?id=$id - skipped');
179+
print('Warning: Could not find $title via lookup id: $feedApiEndpoint/lookup?id=$id - skipped');
185180
}
186181

187182
if (count > 0 && results['results'] != null) {
@@ -197,8 +192,7 @@ final class ITunesSearch extends BaseSearch {
197192
setLastError(e);
198193
}
199194

200-
return SearchResult.fromError(
201-
lastError: lastError ?? '', lastErrorType: lastErrorType);
195+
return SearchResult.fromError(lastError: lastError ?? '', lastErrorType: lastErrorType);
202196
}
203197

204198
/// This internal method constructs a correctly encoded URL which is then
@@ -249,19 +243,15 @@ final class ITunesSearch extends BaseSearch {
249243
}
250244

251245
String _termParam() {
252-
return term != null && term!.isNotEmpty
253-
? '?term=${Uri.encodeComponent(term!)}'
254-
: '';
246+
return term != null && term!.isNotEmpty ? '?term=${Uri.encodeComponent(term!)}' : '';
255247
}
256248

257249
String _countryParam() {
258250
return _country != Country.none ? '&country=${_country.code}' : '';
259251
}
260252

261253
String _attributeParam() {
262-
return _attribute != Attribute.none
263-
? '&attribute=${Uri.encodeComponent(_attribute!.attribute)}'
264-
: '';
254+
return _attribute != Attribute.none ? '&attribute=${Uri.encodeComponent(_attribute!.attribute)}' : '';
265255
}
266256

267257
String _limitParam() {

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: podcast_search
22
description: A library for searching for podcasts and parsing podcast RSS feeds. Supports iTunes and PodcastIndex directories, and newer features such as chapters and transcripts.
33

4-
version: 0.6.8
4+
version: 0.6.9
55
homepage: https://github.com/amugofjava/podcast_search
66

77
environment:

test/podcast_search_test.dart

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@ void main() {
1010

1111
setUp(() {
1212
search = Search(
13-
searchProvider: PodcastIndexProvider(
14-
key: 'XXWQEGULBJABVHZUM8NF',
15-
secret: 'KZ2uy4upvq4t3e\$m\$3r2TeFS2fEpFTAaF92xcNdX'),
13+
searchProvider:
14+
PodcastIndexProvider(key: 'XXWQEGULBJABVHZUM8NF', secret: 'KZ2uy4upvq4t3e\$m\$3r2TeFS2fEpFTAaF92xcNdX'),
1615
);
1716
});
1817

@@ -27,5 +26,19 @@ void main() {
2726

2827
expect(result.resultCount, 1);
2928
});
29+
30+
test('Empty iTunes items result', () async {
31+
final result = Item.fromJson(
32+
json: {},
33+
);
34+
35+
expect(result, isNotNull);
36+
});
37+
38+
test('Empty PodcastIndex items result', () async {
39+
final result = Item.fromJson(json: {}, type: ResultType.podcastIndex);
40+
41+
expect(result, isNotNull);
42+
});
3043
});
3144
}

0 commit comments

Comments
 (0)