Reputation: 105
I'm trying to get a album list from a server, the server uses xml and I'm trying to convert it to json but for some reason it doesn't work/comes back as null.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:xml2json/xml2json.dart';
import 'package:get/get.dart';
import 'package:xml/xml.dart' as xml;
class RecentlyAddedHome extends StatefulWidget {
@override
_RecentlyAddedHomState createState() => _RecentlyAddedHomState();
}
Future<List<AlbumsResponse>> fetchRecentlyAddedAlbums() async{
final aresponse = await http.get(recentAlbumsURL);
xml2json.parse(aresponse.body);
var jsondata = xml2json.toGData();
var data = json.decode(jsondata);
print(data);
return AlbumsResponse.fromJson(data).toList();
}
class _RecentlyAddedHomState extends State<RecentlyAddedHome> {
final Future<List<AlbumsResponse>> albumsresponse = fetchRecentlyAddedAlbums();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder(
future: fetchRecentlyAddedAlbums(),
builder: (context, data){
if (data.hasData){
List<AlbumsResponse> albumsresponse = data.data;
return ListView.builder(
itemCount: albumsresponse.length,
itemBuilder: (context, index){
return ListTile(
title: Text(albumsresponse[index].title,style: TextStyle(fontSize: 25.0),),
);
},
);
}
},
)
)
);
}
}
this is my model for it
import 'package:xml/xml.dart' as xml;
import 'package:music_app_prototype/services/auth.dart';
import 'package:http/http.dart' as http;
class AlbumsResponse {
final String title;
final int albumid;
final String artist;
final int coverart;
AlbumsResponse({this.albumid, this.artist, this.coverart, this.title});
factory AlbumsResponse.fromJson(Map<String, dynamic> json){
return AlbumsResponse(
title: json['_title'] as String,
albumid: json['_albumid'] as int,
artist: json['_artist'] as String,
coverart: json['_coverart'] as int,
);
}
get albumtitle => this.title;
Future<List<AlbumsResponse>> toList() {}
}
and this is what the server sends me when i make the request
<?xml version="1.0" encoding="UTF-8"?>
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.15.0">
<albumList>
<album id="695" parent="577" isDir="true" title="Whatever" album="Whatever" artist="Kaytranada" genre="Hip-Hop" coverArt="695" playCount="0" created="2020-04-18T02:01:55.546Z"/>
<album id="850" parent="581" isDir="true" title="Cruel Intentions" album="Cruel Intentions" artist="Tory Lanez" genre="Hip-Hop" coverArt="850" playCount="1" created="2020-04-18T01:56:48.148Z"/>
<album id="649" parent="574" isDir="true" title="So Far Gone" album="So Far Gone" artist="Drake" year="2009" genre="Hip-Hop/Rap" coverArt="649" playCount="0" created="2020-04-18T01:49:12.120Z"/>
<album id="668" parent="575" isDir="true" title="Myst" album="Myst" artist="Herzeloyde" year="2020" genre="Electro" coverArt="668" playCount="1" created="2020-04-05T03:08:36.596Z"/>
<album id="607" parent="572" isDir="true" title="Survival" album="Survival" artist="Dave East" year="2019" genre="Hip-Hop/Rap" coverArt="607" playCount="2" created="2020-03-01T02:29:48.072Z"/>
<album id="792" parent="580" isDir="true" title="Yikes" album="Yikes" artist="Nicki Minaj" year="2020" genre="Rap/Hip Hop" coverArt="792" playCount="0" created="2020-02-17T04:47:49.067Z"/>
<album id="790" parent="580" isDir="true" title="Sucka Free" album="Sucka Free" artist="Nicki Minaj" year="2008" genre="Hip-Hop" coverArt="790" playCount="0" created="2020-01-02T01:34:11.738Z"/>
<album id="786" parent="580" isDir="true" title="Playtimes Over" album="Playtimes Over" artist="Nicki Minaj" year="2007" genre="Hip-Hop" coverArt="786" playCount="0" created="2020-01-02T01:34:11.716Z"/>
<album id="715" parent="578" isDir="true" title="No Ceilings 2" album="No Ceilings 2" artist="Lil Wayne" year="2009" genre="Hip-Hop" coverArt="715" playCount="0" created="2020-01-02T01:34:04.226Z"/>
<album id="788" parent="580" isDir="true" title="Queen" album="Queen" artist="Nicki Minaj" year="2018" genre="Hip-Hop/Rap" coverArt="788" playCount="0" created="2020-01-02T00:25:00.671Z"/>
</albumList>
</subsonic-response>
When i try to go to the Recently added page it says my build function returned null? I see that i get the data but it still doesn't show up. Can anyone help me, I'm not sure what I'm doing wrong, if i don't have to convert it from xml to json, how to do i work with it in xml form? Thanks!
Upvotes: 0
Views: 4194
Reputation: 54377
You can copy paste run full code below
Step 1: Parse with payloadFromJson
and return data.subsonicResponse.albumList.album
, see full code for detail Payload
class definition
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
...
final aresponse = http.Response(xml, 200);
xml2json.parse(aresponse.body);
var jsondata = xml2json.toGData();
var data = payloadFromJson(jsondata);
var albumList = data.subsonicResponse.albumList.album;
return albumList;
Step 2: builder
need to define type AsyncSnapshot<List<AlbumsResponse>>
and check connectionState
builder: (context, AsyncSnapshot<List<AlbumsResponse>> data) {
switch (data.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (data.hasData) {
working demo
full code
import 'package:flutter/material.dart';
import 'package:xml2json/xml2json.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));
String payloadToJson(Payload data) => json.encode(data.toJson());
class Payload {
Payload({
this.version,
this.encoding,
this.subsonicResponse,
});
String version;
String encoding;
SubsonicResponse subsonicResponse;
factory Payload.fromJson(Map<String, dynamic> json) => Payload(
version: json["version"],
encoding: json["encoding"],
subsonicResponse: SubsonicResponse.fromJson(json["subsonic-response"]),
);
Map<String, dynamic> toJson() => {
"version": version,
"encoding": encoding,
"subsonic-response": subsonicResponse.toJson(),
};
}
class SubsonicResponse {
SubsonicResponse({
this.status,
this.version,
this.xmlns,
this.albumList,
});
String status;
String version;
String xmlns;
AlbumList albumList;
factory SubsonicResponse.fromJson(Map<String, dynamic> json) =>
SubsonicResponse(
status: json["status"],
version: json["version"],
xmlns: json["xmlns"],
albumList: AlbumList.fromJson(json["albumList"]),
);
Map<String, dynamic> toJson() => {
"status": status,
"version": version,
"xmlns": xmlns,
"albumList": albumList.toJson(),
};
}
class AlbumList {
AlbumList({
this.album,
});
List<AlbumsResponse> album;
factory AlbumList.fromJson(Map<String, dynamic> json) => AlbumList(
album: List<AlbumsResponse>.from(
json["album"].map((x) => AlbumsResponse.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"album": List<dynamic>.from(album.map((x) => x.toJson())),
};
}
class AlbumsResponse {
AlbumsResponse({
this.id,
this.parent,
this.isDir,
this.title,
this.album,
this.artist,
this.genre,
this.coverArt,
this.playCount,
this.created,
this.year,
});
String id;
String parent;
String isDir;
String title;
String album;
String artist;
String genre;
String coverArt;
String playCount;
DateTime created;
String year;
factory AlbumsResponse.fromJson(Map<String, dynamic> json) => AlbumsResponse(
id: json["id"],
parent: json["parent"],
isDir: json["isDir"],
title: json["title"],
album: json["album"],
artist: json["artist"],
genre: json["genre"],
coverArt: json["coverArt"],
playCount: json["playCount"],
created: DateTime.parse(json["created"]),
year: json["year"] == null ? null : json["year"],
);
Map<String, dynamic> toJson() => {
"id": id,
"parent": parent,
"isDir": isDir,
"title": title,
"album": album,
"artist": artist,
"genre": genre,
"coverArt": coverArt,
"playCount": playCount,
"created": created.toIso8601String(),
"year": year == null ? null : year,
};
}
Xml2Json xml2json = Xml2Json();
Future<List<AlbumsResponse>> fetchRecentlyAddedAlbums() async {
//final aresponse = await http.get(recentAlbumsURL);
String xml = '''
<?xml version="1.0" encoding="UTF-8"?>
<subsonic-response xmlns="http://subsonic.org/restapi" status="ok" version="1.15.0">
<albumList>
<album id="695" parent="577" isDir="true" title="Whatever" album="Whatever" artist="Kaytranada" genre="Hip-Hop" coverArt="695" playCount="0" created="2020-04-18T02:01:55.546Z"/>
<album id="850" parent="581" isDir="true" title="Cruel Intentions" album="Cruel Intentions" artist="Tory Lanez" genre="Hip-Hop" coverArt="850" playCount="1" created="2020-04-18T01:56:48.148Z"/>
<album id="649" parent="574" isDir="true" title="So Far Gone" album="So Far Gone" artist="Drake" year="2009" genre="Hip-Hop/Rap" coverArt="649" playCount="0" created="2020-04-18T01:49:12.120Z"/>
<album id="668" parent="575" isDir="true" title="Myst" album="Myst" artist="Herzeloyde" year="2020" genre="Electro" coverArt="668" playCount="1" created="2020-04-05T03:08:36.596Z"/>
<album id="607" parent="572" isDir="true" title="Survival" album="Survival" artist="Dave East" year="2019" genre="Hip-Hop/Rap" coverArt="607" playCount="2" created="2020-03-01T02:29:48.072Z"/>
<album id="792" parent="580" isDir="true" title="Yikes" album="Yikes" artist="Nicki Minaj" year="2020" genre="Rap/Hip Hop" coverArt="792" playCount="0" created="2020-02-17T04:47:49.067Z"/>
<album id="790" parent="580" isDir="true" title="Sucka Free" album="Sucka Free" artist="Nicki Minaj" year="2008" genre="Hip-Hop" coverArt="790" playCount="0" created="2020-01-02T01:34:11.738Z"/>
<album id="786" parent="580" isDir="true" title="Playtimes Over" album="Playtimes Over" artist="Nicki Minaj" year="2007" genre="Hip-Hop" coverArt="786" playCount="0" created="2020-01-02T01:34:11.716Z"/>
<album id="715" parent="578" isDir="true" title="No Ceilings 2" album="No Ceilings 2" artist="Lil Wayne" year="2009" genre="Hip-Hop" coverArt="715" playCount="0" created="2020-01-02T01:34:04.226Z"/>
<album id="788" parent="580" isDir="true" title="Queen" album="Queen" artist="Nicki Minaj" year="2018" genre="Hip-Hop/Rap" coverArt="788" playCount="0" created="2020-01-02T00:25:00.671Z"/>
</albumList>
</subsonic-response>
''';
final aresponse = http.Response(xml, 200);
xml2json.parse(aresponse.body);
var jsondata = xml2json.toGData();
var data = payloadFromJson(jsondata);
var albumList = data.subsonicResponse.albumList.album;
//print(albumList.toString());
return albumList;
}
class RecentlyAddedHome extends StatefulWidget {
@override
_RecentlyAddedHomState createState() => _RecentlyAddedHomState();
}
class _RecentlyAddedHomState extends State<RecentlyAddedHome> {
final Future<List<AlbumsResponse>> albumsresponse =
fetchRecentlyAddedAlbums();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder(
future: fetchRecentlyAddedAlbums(),
builder: (context, AsyncSnapshot<List<AlbumsResponse>> data) {
switch (data.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (data.hasData) {
List<AlbumsResponse> albumsresponse = data.data;
return ListView.builder(
itemCount: albumsresponse.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
albumsresponse[index].title,
style: TextStyle(fontSize: 25.0),
),
);
},
);
}
}
},
)));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: RecentlyAddedHome(),
);
}
}
Upvotes: 2