json - Flutter Dart Http XML rest转换为Json

标签 json xml rest flutter dart

我正在尝试从服务器获取专辑列表,该服务器使用xml,并且试图将其转换为json,但是由于某种原因,它不起作用/返回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),),
                );
              }, 
              );
            }
          },
        )
      )
    );
  }
}


这是我的模型
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() {}
}

这是我发出请求时服务器发送给我的内容
<?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>

当我尝试转到“最近添加的页面”时,它说我的构建函数返回null?我看到我得到了数据,但仍然没有显示。谁能帮我,我不确定我在做什么错,如果我不必将其从xml转换为json,我该如何以xml形式使用它?
谢谢!

最佳答案

您可以在下面复制粘贴运行完整代码
第1步:使用payloadFromJson解析并返回data.subsonicResponse.albumList.album,有关完整的Payload类定义,请参见完整代码

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;

步骤2:builder需要定义AsyncSnapshot<List<AlbumsResponse>>类型并检查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) {

工作演示

enter image description here

完整的代码
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(),
    );
  }
}

关于json - Flutter Dart Http XML rest转换为Json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62124231/

相关文章:

python - 使用多个嵌套 json 扩展数据框

ruby-on-rails - 如何为嵌套的足智多谋的路线制作更短的路径

java - 异常(exception)是 REST Jersey

ios - 为什么从此 URL 检索数据返回 nil?

javascript - JSON 对象转换为特定的 Javascript 数组或 JSON 对象

xml - XML 文档的第一行是什么?

java - res/values/strings.xml 中的字符串数组

javascript - JQuery Ajax POST XML 结构/过滤器链

rest - 如何设计 URL 以在 REST API 中从当前用户返回数据?

asp.net - 从 MVC 中的 Controller 返回 JSON 中的部分 View