在Flutter中将Json解析为对象列表的正确方法

时间:2019-06-18 18:18:31

标签: flutter dart

在调用Webservice之后,我会得到如下的json数据:

{myteam: [
{'id': '1', name: 'xy'},
{'id': '2', name: 'zx'},
{'id': '3', name: 'gh'}
]}

我在Flutter上了一堂课

class CardData {
int id;
String name;
CardData({this.id, this.name});
} 

我通过以下方式将数据解析为CardData列表:

List<CardData> CardsList = [];

List cards = List();

我得到了数据:

Map<String, dynamic> map = await ws.getData();

放入列表

cards = map['myteam'];

然后迭代卡片:

cards.forEach((f) {
CardsList.add(CardData(id: f['id'], name: f['name']));
}

我知道,这不是最好的方法,而是有效的方法。现在,请帮助我,我该如何为该任务制定适当的解决方案。

3 个答案:

答案 0 :(得分:0)

您可以使用这样的逻辑来解析您的Json:

class _MyHomePageState extends State<MyHomePage> {
  String jsonList = '{"myteam":[{"id":"1","name":"xy"},{"id": "2","name":"zx"},{"id":"3","name": "gh"}]}';

  Future<List<CardData>> listOfItems() async {
    var parse = json.decode(jsonList);
    var data = parse['myteam'] as List;
    var map = data.map<CardData>((json) => CardData.parseJson(json));
    return map.toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        child: Center(
          child: FutureBuilder<List<CardData>>(
            future: listOfItems(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                return Text(snapshot.data[0].name);
              } else {
                return Text("Loading...");
              }
            },
          ),
        ),
      ),
    );
  }
}

class CardData {
  String id;
  String name;

  CardData({this.id, this.name});

  factory CardData.parseJson(Map<String, dynamic> json) {
    return CardData(id: json['id'], name: json['name']);
  }
}

现在,您的Json正在使用String作为ID(您应该删除引号以使其成为Integer)。另外,您myteam Json数组键没有任何引号。

答案 1 :(得分:0)

此代码将执行您的工作:

import 'dart:convert';

import 'json_objects.dart';

void main() {
  var json = jsonDecode(_data) as Map<String, dynamic>;
  var data = Data.fromJson(json);
  var cardList = <CardData>[];
  for (var card in data.myteam) {
    cardList.add(card);
  }  
}

var _data = '''
{
  "myteam": [
    {
      "id": 1,
      "name": "xy"
    },
    {
      "id": 2,
      "name": "x"
    },
    {
      "id": 3,
      "name": "gh"
    }
  ]
}''';

数据模型(“ json_objects.dart”):

class CardData {
  final int id;
  final String name;

  CardData({this.id, this.name});

  factory CardData.fromJson(Map<String, dynamic> json) {
    return CardData(
      id: json['id'] as int,
      name: json['name'] as String,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
    };
  }
}

class Data {
  final List<CardData> myteam;

  Data({this.myteam});

  factory Data.fromJson(Map<String, dynamic> json) {
    return Data(
      myteam: _toObjectList(json['myteam'], (e) => CardData.fromJson(e)),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'myteam': _fromList(myteam, (e) => e.toJson()),
    };
  }
}

List _fromList(data, Function(dynamic) toJson) {
  if (data == null) {
    return null;
  }
  var result = [];
  for (var element in data) {
    var value;
    if (element != null) {
      value = toJson(element);
    }
    result.add(value);
  }
  return result;
}

List<T> _toObjectList<T>(data, T Function(Map<String, dynamic>) fromJson) {
  if (data == null) {
    return null;
  }
  var result = <T>[];
  for (var element in data) {
    T value;
    if (element != null) {
      value = fromJson(element as Map<String, dynamic>);
    }
    result.add(value);
  }
  return result;
}

/*
Data:
  myteam: List<CardData>

CardData:
  id: int
  name: String
*/

答案 2 :(得分:0)

您的解析看起来很不错,我可以指出的一点点变化可能是CardData的构造函数不需要可选参数,并且您可以有一个命名构造函数以https://dart.dev/guides/language/language-tour的形式从json构建Cards鼓励:

CardData.fromJson(Map<String, String> json)
    : id = json['id'],
      name = json['name'];

然后从服务器获取数据时使用它:

cards.forEach((f) {
CardsList.add(CardData.fromJson(f));
}

另一件事是,如果整个响应对您的域(由卡片阵列组成的团队部分)意味着某种意义,则应考虑创建一个类来解析整个数据,并避免使用:

cards = map['myteam'];