【问题标题】:How to identify "type 'List<String>' is not a subtype of type 'String' in type cast"如何识别“类型'List<String>'不是类型转换中'String'类型的子类型”
【发布时间】:2020-06-19 20:26:47
【问题描述】:

我了解这个错误是什么,但我无法确定是我的代码的哪一部分导致了它。

我如何识别和理解我的代码的哪一部分导致了这种情况?

我创建了一些非常基本的单元测试来验证我的 fromJson/jsonDecode 和 toJson/jsonEncode 函数,并且在使用嵌套类/列表时,除了 fromJson 之外,一切都按我的意愿工作。

使用toJson/jsonEncode时,我能够成功生成如下字符串

{"id":1,"title":"The Hits","songList":[{"id":1,"title":"hello","artist":"me","lyrics":"say stuff","genre":"rock","rank":10,"created":"2020-04-06T22:00:00.000"},{"id":2,"title":"howdy","artist":"you","lyrics":"say no","genre":"hillBilly","rank":9,"created":"2019-04-06T22:00:00.000"},{"id":3,"title":"Ola","artist":"we","lyrics":"say  nothing","genre":"Flapp","rank":2,"created":"2018-04-06T22:00:00.000"}],"created":"2018-04-06T22:00:00.000"}

我不明白为什么 fromJson/Decode 因转换错误而失败。

单元测试

test('Create Setlist including songList from complex json', (){
    Setlist complexSet = Setlist.fromJson(jsonDecode(complexObjectJson));
    print(complexSet);
  });

这是来自 Setlist 类的 Setlist.fromJson 工厂方法

factory Setlist.fromJson(dynamic json) {
    if (json['songList'] != null) {
      var songObjsJson = json['songList'] as List;
      List<Song> _songs = songObjsJson.map((songJson) => Song.fromJson(songJson)).toList();

      return Setlist(
        id: json['id'] as int,
        title: json['title'] as String,
        songList: _songs,
        created: ['created'] as String,
      );
    } else {
      return Setlist(
        id: json['id'] as int,
        title: json['title'] as String,
        created: ['created'] as String,
      );
    }
  }

歌曲课

class Song {
  final int id;
  final String title;
  final String artist;
  final String lyrics;
  final String genre;
  final int rank;
  final String created;

  Song(
      {this.id,
      this.title,
      this.artist,
      this.lyrics,
      this.genre,
      this.rank,
      this.created});

  Map toJson() => {
        'id': id,
        'title': title,
        'artist': artist,
        'lyrics': lyrics,
        'genre': genre,
        'rank': rank,
        'created': created,
      };

  factory Song.fromJson(dynamic json) {
    return Song(
        id: json['id'] as int,
        title: json['title'] as String,
        artist: json['artist'] as String,
        lyrics: json['lyrics'] as String,
        genre: json['genre'] as String,
        rank: json['rank'] as int,
        created: json['created'] as String);
  }

  @override
  String toString() {
    return 'Song{id: $id, '
        'title: $title, '
        'artist: $artist, '
        'lyrics: $lyrics, '
        'genre: $genre, '
        'rank: $rank, '
        'created: $created}';
  }
}

【问题讨论】:

  • 你能从堆栈跟踪中检查哪一行导致错误吗?

标签: flutter dart


【解决方案1】:

我刚刚使用您提供的 json 创建了一个示例示例,请查看:

以下是json:

{
    "id": 1,
    "title": "The Hits",
    "songList": [{
        "id": 1,
        "title": "hello",
        "artist": "me",
        "lyrics": "say stuff",
        "genre": "rock",
        "rank": 10,
        "created": "2020-04-06T22:00:00.000"
    }, {
        "id": 2,
        "title": "howdy",
        "artist": "you",
        "lyrics": "say no",
        "genre": "hillBilly",
        "rank": 9,
        "created": "2019-04-06T22:00:00.000"
    }, {
        "id": 3,
        "title": "Ola",
        "artist": "we",
        "lyrics": "say  nothing",
        "genre": "Flapp",
        "rank": 2,
        "created": "2018-04-06T22:00:00.000"
    }],
    "created": "2018-04-06T22:00:00.000"
}

稍后会出现您提供的 json 的模式:

// To parse this JSON data, do
//
//     final song = songFromJson(jsonString);

import 'dart:convert';

Song songFromJson(String str) => Song.fromJson(json.decode(str));

String songToJson(Song data) => json.encode(data.toJson());

class Song {
    int id;
    String title;
    List<SongList> songList;
    DateTime created;

    Song({
        this.id,
        this.title,
        this.songList,
        this.created,
    });

    factory Song.fromJson(Map<String, dynamic> json) => Song(
        id: json["id"],
        title: json["title"],
        songList: List<SongList>.from(json["songList"].map((x) => SongList.fromJson(x))),
        created: DateTime.parse(json["created"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "songList": List<dynamic>.from(songList.map((x) => x.toJson())),
        "created": created.toIso8601String(),
    };
}

class SongList {
    int id;
    String title;
    String artist;
    String lyrics;
    String genre;
    int rank;
    DateTime created;

    SongList({
        this.id,
        this.title,
        this.artist,
        this.lyrics,
        this.genre,
        this.rank,
        this.created,
    });

    factory SongList.fromJson(Map<String, dynamic> json) => SongList(
        id: json["id"],
        title: json["title"],
        artist: json["artist"],
        lyrics: json["lyrics"],
        genre: json["genre"],
        rank: json["rank"],
        created: DateTime.parse(json["created"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "artist": artist,
        "lyrics": lyrics,
        "genre": genre,
        "rank": rank,
        "created": created.toIso8601String(),
    };
}

这是从 json 渲染 ui 的主文件:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'dummy.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<SongList> songList = List();
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    loadYourData();
  }

  Future<String> loadFromAssets() async {
    return await rootBundle.loadString('json/parse.json');
  }

  loadYourData() async {
    setState(() {
      _isLoading = true;
    });
    String jsonString = await loadFromAssets();
    final song = songFromJson(jsonString);
    // here you get the complete object
    songList = song.songList;
    setState(() {
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          child: _isLoading
              ? CircularProgressIndicator()
              : ListView.builder(
                  itemCount: songList.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Card(
                      child: Column(

                        children: <Widget>[
                          Text(songList[index].artist),
                          Text(songList[index].genre),
                          Text(songList[index].id.toString()),
                          Text(songList[index].title)
                        ],
                      ),
                    );
                  },
                ),
        ),
      ),
    );
  }
}

让我知道它是否有效。

【讨论】:

  • 我已经检查了您的代码,可以将其换成我拥有的代码,但我仍然对了解问题所在以及转换错误来自何处/如何修复它非常感兴趣。如果您可以在那里提供任何见解,我将不胜感激。
  • 如果它解决了你的问题,那就太好了,你问的问题是错误在哪里,所以你能把完整的模型类放在一边,这样我就可以告诉你了。 (只需在您的问题模型类中进行编辑)
【解决方案2】:

您的song 课程似乎是错误的,

试试这个

class Song {
    int id;
    String title;
    List<SongList> songList;
    DateTime created;

    Song({
        this.id,
        this.title,
        this.songList,
        this.created,
    });

    factory Song.fromJson(Map<String, dynamic> json) => Song(
        id: json["id"],
        title: json["title"],
        songList: List<SongList>.from(json["songList"].map((x) => SongList.fromJson(x))),
        created: DateTime.parse(json["created"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "songList": List<dynamic>.from(songList.map((x) => x.toJson())),
        "created": created.toIso8601String(),
    };
}

class SongList {
    int id;
    String title;
    String artist;
    String lyrics;
    String genre;
    int rank;
    DateTime created;

    SongList({
        this.id,
        this.title,
        this.artist,
        this.lyrics,
        this.genre,
        this.rank,
        this.created,
    });

    factory SongList.fromJson(Map<String, dynamic> json) => SongList(
        id: json["id"],
        title: json["title"],
        artist: json["artist"],
        lyrics: json["lyrics"],
        genre: json["genre"],
        rank: json["rank"],
        created: DateTime.parse(json["created"]),
    );

    Map<String, dynamic> toJson() => {
        "id": id,
        "title": title,
        "artist": artist,
        "lyrics": lyrics,
        "genre": genre,
        "rank": rank,
        "created": created.toIso8601String(),
    };
}

【讨论】:

  • 感谢您的回复。不幸的是,您的示例与我提供的模型/示例不匹配。一首歌曲不包含一个歌曲列表。我有一个名为 Setlist 的类,它有一个 title、id、created 和 List 对象。提供的 json 字符串显示了一个包含歌曲列表的“Setlist”。我想了解我的代码中的强制转换异常来自哪里,而不是用完全不同的方法重新启动,这与我想要做的事情不匹配。
猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
  • 2021-11-07
  • 2021-08-29
  • 2020-11-24
相关资源
最近更新 更多