【问题标题】:Flutter - Errors when trying to save JSON Array to ListFlutter - 尝试将 JSON 数组保存到列表时出错
【发布时间】:2021-03-08 23:00:17
【问题描述】:

我是 Flutter 的新手,并试图将 API 数据提取到列表中。我的目标是稍后将该信息输入到 ListView 中。

我熟悉 api 调用,但现在我正在尝试从 json 数组中获取信息。以前我创建了一个模型类来检索我需要继续我的过程的对象,但我已经走到了死胡同,因为我似乎无法弄清楚如何正确地从数组中提取对象。

我正在使用多个文件。 “API 服务”、“readData 模型”以及将显示数据的实际屏幕。

其他一切都很好,只是我无法将数据实际保存到列表中。

首先,我将向您展示我的代码是如何设置的以及我尝试保存的 JSON 响应数据:

JSON 响应正文:

我展示的示例只有一个图像数据块,但我们需要一个数组,因为它应该显示列表中的每个块。

 {"status":200,
  "content":[{"image_id":"151",
              "image_url":"https:\\\/imageurl.jpg",
              "returned_value":"14.0",
              "alarm":"false",
              "account":"test@email.com",
              "create_at":"2020-11-17 07:13:42",
              "location":"NY"
             }]
  }

API POST 功能:

  Future<ReadResponseModel> readData(
      ReadRequestModel requestData) async {


   final response = await http.post("$url/read",
        body: requestData.toJson() ,
        headers: {
    "Client-Service": "frontend-client",
    "Auth-Key": "simplerestapi",
    "Content-Type":"application/x-www-form-urlencoded",
    "Authorization": token,
    "User-ID": userId,
    });

    print(response.body);
    if (response.statusCode == 200 || response.statusCode == 400) {
      dynamic resBody = json.decode(response.body);
      return ReadResponseModel.fromJson(resBody);
    } else {
      throw Exception('Failed to load data!');
    }
  }

readResponseModel 类: 我尝试了两种方法来处理这些信息,但都失败了。

这是方法一:

这个会给我以下错误:[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'

最初设置为所有值的最终字符串,但由于我收到此错误,我一直在尝试确保每个值都是正确的类型(例如,retVal 为 int 或 alarm 为 bool)。到目前为止仍然没有运气。

class ReadResponseModel {
  final dynamic imageID;
  final dynamic imgUrl;
  final dynamic retVal;
  final bool alarm;
  final dynamic account;
  final dynamic createAt;
  final dynamic location;

  ReadResponseModel({this.imageID, this.imgUrl, this.retVal, this.alarm,
    this.account, this.createAt, this.location,});

  factory ReadResponseModel.fromJson(Map<String , dynamic> json) {
    return ReadResponseModel(
      imageID: json['content']['image_id'] as String ,
      imgUrl: json['content']['image_url'] as String ,
      retVal: json['content']["returned_value"] as String,
      alarm: json['content']['alarm'] as bool ,
      account: json['content']['account'] as String,
      createAt: json['content']['create_at'] as String,
      location: json['content']['location'] as String,
    );
  }
}

方法二:

这会给我以下错误: [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type '(dynamic) =&gt; Content' is not a subtype of type '(dynamic) =&gt; String' of 'f' -- 我什至不知道那个 f 是从哪里来的。

class ReadResponseModel {
  List<String> content;
  ReadResponseModel({this.content});

  factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
    return ReadResponseModel(
      content: json['content'] != null
          ? json['content']
              .map<String>((json) => Content.fromJson(json))
              .toList()
          : null,
    );
  }
}

class Content {
  final String imageID;
  final String imgUrl;
  final String retVal;
  final String alarm;
  final String account;
  final String createAt;
  final String location;
  final String error;

  Content({this.imageID,
    this.imgUrl,
    this.retVal,
    this.alarm,
    this.account,
    this.createAt,
    this.location,
    this.error});

  factory Content.fromJson(Map<String, dynamic> json) =>
      Content(
        imageID: json['image_id'],
        imgUrl: json['s3_url'],
        retVal: json['predict'],
        alarm: json['alarm'],
        account: json['account'],
        createAt: json['create_at'],
        location: json['location'],
      );
}

以下代码正是我正在做的将所有这些连接到我的小部件:

APIService readService = new APIService();
      readRequestModel.companyID = "123";

      readService.readData(readRequestModel).then((value) async {
         if (value != null) {
           setState(() {
             isApiCallProcess = false;
           });
       ///Trying to call the fetched data and show it in the console:
            print("Account: ${value.account}");
            print("Returned Value: ${value.retVal}");
            print("Image ID: ${value.imgUrl}");
         }

我不完全确定为什么会出现这些错误,对于方法 2,我什至不知道“f”来自哪里。如果有人能对这个主题有所了解,将不胜感激。

【问题讨论】:

  • 也许警报是String,而不是bool
  • 最初都是String,我一直在更改类型以确保这不是问题的根源。还是没有运气

标签: json api rest flutter dart


【解决方案1】:

您可以在下面复制粘贴运行完整代码
第 1 步:使用 List&lt;Content&gt; content; 而不是 List&lt;String&gt;
第 2 步:使用List&lt;Content&gt;.from(json["content"].map((x) =&gt; Content.fromJson(x)))
第3步:在样本JSONimage_url不等于模型的s3_url,您需要修改以更正一个
代码sn-p

class ReadResponseModel {
  List<Content> content;
  ReadResponseModel({this.content});

  factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
    return ReadResponseModel(
      content: json['content'] != null
          ? List<Content>.from(json["content"].map((x) => Content.fromJson(x)))
          : null,
    );
  }
}
...
dynamic resBody = json.decode(jsonString);
ReadResponseModel model = ReadResponseModel.fromJson(resBody);
print(model.content[0].account);

输出

I/flutter ( 4426): test@email.com

完整代码

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

class ReadResponseModel {
  List<Content> content;
  ReadResponseModel({this.content});

  factory ReadResponseModel.fromJson(Map<String, dynamic> json) {
    return ReadResponseModel(
      content: json['content'] != null
          ? List<Content>.from(json["content"].map((x) => Content.fromJson(x)))
          : null,
    );
  }
}

class Content {
  final String imageID;
  final String imgUrl;
  final String retVal;
  final String alarm;
  final String account;
  final String createAt;
  final String location;
  final String error;

  Content(
      {this.imageID,
      this.imgUrl,
      this.retVal,
      this.alarm,
      this.account,
      this.createAt,
      this.location,
      this.error});

  factory Content.fromJson(Map<String, dynamic> json) => Content(
        imageID: json['image_id'],
        imgUrl: json['s3_url'],
        retVal: json['predict'],
        alarm: json['alarm'],
        account: json['account'],
        createAt: json['create_at'],
        location: json['location'],
      );
}

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: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    String jsonString = '''
    {"status":200,
  "content":[{"image_id":"151",
              "image_url":"https:\\\/imageurl.jpg",
              "returned_value":"14.0",
              "alarm":"false",
              "account":"test@email.com",
              "create_at":"2020-11-17 07:13:42",
              "location":"NY"
             }]
  }
    ''';

    dynamic resBody = json.decode(jsonString);
    ReadResponseModel model = ReadResponseModel.fromJson(resBody);
    print(model.content[0].account);

    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

【讨论】:

  • 谢谢,工作完美。愿所有网点与你同在
【解决方案2】:

从上面提到的代码我为你创建了一个示例,基本上你是在搞乱模式类。看看下面的例子。

您提供的 JSON:

{"status":200,
    "content":[{"image_id":"151",
                "image_url":"https:\\\/imageurl.jpg",
                "returned_value":"14.0",
                "alarm":"false",
                "account":"test@email.com",
                "create_at":"2020-11-17 07:13:42",
                "location":"NY"
               }]
    }

基于json的模型类如下:

// To parse this JSON data, do
//
//     final readResponseModel = readResponseModelFromJson(jsonString);

import 'dart:convert';

ReadResponseModel readResponseModelFromJson(String str) => ReadResponseModel.fromJson(json.decode(str));

String readResponseModelToJson(ReadResponseModel data) => json.encode(data.toJson());

class ReadResponseModel {
    ReadResponseModel({
        this.status,
        this.content,
    });

    int status;
    List<Content> content;

    factory ReadResponseModel.fromJson(Map<String, dynamic> json) => ReadResponseModel(
        status: json["status"],
        content: List<Content>.from(json["content"].map((x) => Content.fromJson(x))),
    );

    Map<String, dynamic> toJson() => {
        "status": status,
        "content": List<dynamic>.from(content.map((x) => x.toJson())),
    };
}

class Content {
    Content({
        this.imageId,
        this.imageUrl,
        this.returnedValue,
        this.alarm,
        this.account,
        this.createAt,
        this.location,
    });

    String imageId;
    String imageUrl;
    String returnedValue;
    String alarm;
    String account;
    DateTime createAt;
    String location;

    factory Content.fromJson(Map<String, dynamic> json) => Content(
        imageId: json["image_id"],
        imageUrl: json["image_url"],
        returnedValue: json["returned_value"],
        alarm: json["alarm"],
        account: json["account"],
        createAt: DateTime.parse(json["create_at"]),
        location: json["location"],
    );

    Map<String, dynamic> toJson() => {
        "image_id": imageId,
        "image_url": imageUrl,
        "returned_value": returnedValue,
        "alarm": alarm,
        "account": account,
        "create_at": createAt.toIso8601String(),
        "location": location,
    };
}

它们是获取数据并在列表视图中显示的主要类。

import 'package:flutter/material.dart';
import 'package:json_parsing_example/model2.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SampleApp(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class SampleApp extends StatefulWidget {
  @override
  _SampleAppState createState() => _SampleAppState();
}

class _SampleAppState extends State<SampleApp> {
  bool _isLoading = false;
  List<Content> list = List();

  fetchData() async {
    setState(() {
      _isLoading = true;
    });

    String data =
        await DefaultAssetBundle.of(context).loadString("json/parse.json");

    // This is the above where you get the remote data
    // Like var response = await get or post
    

    final readResponseModel = readResponseModelFromJson(data);

    list = readResponseModel.content;

    setState(() {
      _isLoading = false;
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Your heading'),
        ),
        body: Container(
            child: _isLoading
                ? Center(child: CircularProgressIndicator())
                : Column(
                    children: <Widget>[
                      ListView.builder(
                          shrinkWrap: true,
                          itemCount: list.length,
                          itemBuilder: (context, index) {
                            return Card(
                              child: Column(
                                children: <Widget>[
                                  
                                  Text('${list[index].account}'),
                                  Text('${list[index].location}')
                                ],
                              ),
                            );
                          })
                    ],
                  )));
  }
}

让我知道它是否有效

【讨论】:

  • 我没有使用完全相同的代码,因为我必须调整一些部分来适应我的,但这很棒。感谢您的帮助!
【解决方案3】:

您可以尝试将returned_value 和image_id 设置为int 而不是string 并尝试一下吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2016-04-05
    相关资源
    最近更新 更多