Flutter-Json序列化无法正常工作

时间:2020-06-01 04:10:06

标签: flutter dart

我遇到了将数据从服务传递到模型的问题。该模型应该从服务中获取json,该json从API中获取数据,然后json将其转换为模型。但是,在数据传递到模型中之后,Map toJson没有处理。 我已经尝试了很多方法,但是结果还是一样。

goals_view_service.dart

import 'dart:convert';
import 'package:requests/requests.dart';


// goal_data={
  //        [
//         'goal_name': savings_goal[1],
//         'amount': savings_goal[2],
//         'duration': savings_goal[3],
//       ]
//          }

class GoalViewServices{

  // List<GoalsModel> _goals;
  var goals = List<GoalsModel>();

   Future<Map<String, dynamic>> _getGoals() async {
      Response request;
      try {
        request = await Requests.get(
          url + '/savings_goal_display',
          headers: {'content-type': 'application/json'},
          // TODO: when having true ssl certificate, change verify to true.
          // verify: false,
          timeoutSeconds: 20,
        );
      } catch (e) {
        return {"result": "Connection Error: $e"};
      }
      if (!request.hasError) {
        try {
          return request.json() as Map<String, dynamic>;
        } catch (e) {
          return {"result": "$e"};
        }
      } else {
        return {"result": "Unknown Request Error"};
      }
  }


  Future<List<GoalsModel>> renewDataForView() async {
    var dic = await _getGoals();
    // var goals = List<GoalsModel>();
    if (dic != null) {
      // print(dic);
      // final savingsGoalsDic = dic['saving_goals'];
      final savingsGoalsDicArray = List<Map<String, dynamic>>.from(dic['savings_goals'] ?? {}) ?? [];
      // final savingsGoalsDicArray = (dic['savings_goals'] ?? {}) ?? [];
      print('savingsGoalsDic__: $savingsGoalsDicArray');
      for (final aData in savingsGoalsDicArray) {
          // print(aData);
          // Map json = jsonDecode(aData);
          // var title = aData["goal_name"];
          // var totalAmount = aData["amount"];
          // var durations = aData["duration"];
          goals.add(GoalsModel.fromJson(aData));
        }
    }
    // print(goals);
    return goals;
  }

}

goals_model.dart

class GoalsModel {
  String title;
  String imagePath;
  int totalAmount;
  int durations;

  GoalsModel({this.title,this.totalAmount,this.durations});

  // final Map<String, String> goalsImage = {
  //   "Housing": "assets/images/housing.jpg",
  //   "Car": "assets/images/car.jpg",
  //   "Retirement": "assets/images/retirement.jpg",
  //   "Shopping": "assets/images/shopping.jpg",
  //   "Travel": "assets/images/travel.jpg",
  //   "Wedding": "assets/images/wedding.jpg",
  //   "Study": "assets/images/study.jpg"
  // };

  GoalsModel.fromJson(Map<String, dynamic> json) {

    // print(json);
    title = json["goal_name"] as String;
    // print(this.title);
    totalAmount = json["amount"] as int;
    // print(this.totalAmount);
    durations = json["duration"] as int;
    // print(this.durations);
    imagePath = "assets/images/study.jpg";
    // var data = _toJson(this.title,this.imagePath,this.totalAmount,this.durations);    

    // if (this.title == goals.keys){
    //     this.imagePath = goals.values;
    // }
  }

  // GoalsModel.fromJson(Map<String, dynamic> json)
  //     : title = json["goal_name"],
  //       totalAmount = json["amount"],
  //       durations = json["duration"],
  //        imagePath = "assets/images/study.jpg";

  Map<String, dynamic> toJson () =>{
    'title' : title,
    'imagePath' :imagePath,
    'totalAmount' : totalAmount,
    'durations': durations,

  };

}

Goals_viewmodels.dart

class GoalsViewModel extends BaseModel {
    GoalViewServices _goalViewServices=locator<GoalViewServices>();

    List<GoalsModel> goalList;

    Future<List<GoalsModel>> getGoals() async {
    setState(ViewState.Busy);
    goalList = await _goalViewServices.renewDataForView();
    print(goalList);
    setState(ViewState.Idle);
    return goalList;
  }

}

目标字典

savingsGoalsDic__: [{amount: 123, duration: 3, goal_name: Car}, {amount: 123, duration: 2, goal_name: Housing}, {amount: 0, duration: 5, goal_name: Retirement}, {amount: 0, duration: 2, goal_name: Shopping}, {amount: 0, duration: 2, goal_name: Travel}, {amount: 12, duration: 3, goal_name: Wedding}]

Goals_model的结果

[Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel', Instance of 'GoalsModel']

1 个答案:

答案 0 :(得分:0)

您可以在下面复制粘贴运行完整代码
步骤1:_getGoals()需要为json.decode(response.body);返回Map<String, dynamic>

Future<Map<String, dynamic>> _getGoals() async {
    String jsonString = '''
    ...
    ''';
    http.Response response = http.Response(jsonString, 200);

    return json.decode(response.body);

第2步:renewDataForView()可以使用Payload.fromJson参见完整代码中的定义

Future<List<GoalsModel>> renewDataForView() async {
    var dic = await _getGoals();
    Payload payload;
    if (dic != null) {
      payload = Payload.fromJson(dic);
    }
    // print(goals);
    return payload.savingsGoalsDic;
  } 

工作演示

enter image description here

完整代码

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

Payload payloadFromJson(String str) => Payload.fromJson(json.decode(str));

String payloadToJson(Payload data) => json.encode(data.toJson());

class Payload {
  Payload({
    this.savingsGoalsDic,
  });

  List<GoalsModel> savingsGoalsDic;

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        savingsGoalsDic: List<GoalsModel>.from(
            json["savingsGoalsDic__"].map((x) => GoalsModel.fromJson(x))),
      );

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

class GoalsModel {
  GoalsModel({
    this.totalAmount,
    this.durations,
    this.title,
  });

  int totalAmount;
  int durations;
  String title;

  factory GoalsModel.fromJson(Map<String, dynamic> json) => GoalsModel(
        totalAmount: json["amount"],
        durations: json["duration"],
        title: json["goal_name"],
      );

  Map<String, dynamic> toJson() => {
        "amount": totalAmount,
        "duration": durations,
        "goal_name": title,
      };
}

class GoalViewServices {
  // List<GoalsModel> _goals;
  var goals = List<GoalsModel>();

  Future<Map<String, dynamic>> _getGoals() async {
    String jsonString = '''
    {"savingsGoalsDic__": [{"amount": 123, "duration": 3, "goal_name": "Car"}, {"amount": 123, "duration": 2, "goal_name": "Housing"}, {"amount": 0, "duration": 5, "goal_name": "Retirement"}, {"amount": 0, "duration": 2, "goal_name": "Shopping"}, {"amount": 0, "duration": 2, "goal_name": "Travel"}, {"amount": 12, "duration": 3, "goal_name": "Wedding"}
]
}
    ''';
    http.Response response = http.Response(jsonString, 200);

    return json.decode(response.body);

    /*Response request;
    try {
      request = await Requests.get(
        url + '/savings_goal_display',
        headers: {'content-type': 'application/json'},
        // TODO: when having true ssl certificate, change verify to true.
        // verify: false,
        timeoutSeconds: 20,
      );
    } catch (e) {
      return {"result": "Connection Error: $e"};
    }
    if (!request.hasError) {
      try {
        return request.json() as Map<String, dynamic>;
      } catch (e) {
        return {"result": "$e"};
      }
    } else {
      return {"result": "Unknown Request Error"};
    }*/
  }

  Future<List<GoalsModel>> renewDataForView() async {
    var dic = await _getGoals();
    Payload payload;
    if (dic != null) {
      payload = Payload.fromJson(dic);
    }
    // print(goals);
    return payload.savingsGoalsDic;
  }
}

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> {
  GoalViewServices goalViewServices = GoalViewServices();

  Future<List<GoalsModel>> _future;

  @override
  void initState() {
    _future = goalViewServices.renewDataForView();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: FutureBuilder(
            future: _future,
            builder: (context, AsyncSnapshot<List<GoalsModel>> snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  return Text('none');
                case ConnectionState.waiting:
                  return Center(child: CircularProgressIndicator());
                case ConnectionState.active:
                  return Text('');
                case ConnectionState.done:
                  if (snapshot.hasError) {
                    return Text(
                      '${snapshot.error}',
                      style: TextStyle(color: Colors.red),
                    );
                  } else {
                    return ListView.builder(
                        itemCount: snapshot.data.length,
                        itemBuilder: (context, index) {
                          return Card(
                              elevation: 6.0,
                              child: Padding(
                                padding: const EdgeInsets.only(
                                    top: 6.0,
                                    bottom: 6.0,
                                    left: 8.0,
                                    right: 8.0),
                                child: Row(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    Text(snapshot.data[index].title),
                                    Spacer(),
                                    Text(
                                      snapshot.data[index].totalAmount
                                          .toString(),
                                    ),
                                  ],
                                ),
                              ));
                        });
                  }
              }
            }));
  }
}