Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
335 views
in Technique[技术] by (71.8m points)

flutter - Can't decode/Parse Json type list<String> with this list<String> type Model in Dart

I wanted to create a drop down from json list. I am using app.quicktype.io to covert json to PODO (Plain Old dart Object)

Here is the My JSON data:

[
  {
    "country_name": "Andorra",
    "alpha2_code": "AD",
    "country_code": "376",
    "states": [
      { "state_name": "Andorra la Vella" },
      { "state_name": "Canillo" }
    ]
  },
  ]

And here is the PODO (Plain Old Dart Object) I created with app.quicktype.io:

class CountryDetailsModel {
  CountryDetailsModel({
    this.countryName,
    this.alpha2Code,
    this.countryCode,
    this.states,
  });

  String countryName;
  String alpha2Code;
  String countryCode;
  List<StateNames> states;

  factory CountryDetailsModel.fromJson(Map<String, dynamic> json) =>
      CountryDetailsModel(
        countryName: json["country_name"],
        alpha2Code: json["alpha2_code"],
        countryCode: json["country_code"],
        states: List<StateNames>.from(
            json["states"].map((x) => StateNames.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "country_name": countryName,
        "alpha2_code": alpha2Code,
        "country_code": countryCode,
        "states": List<dynamic>.from(states.map((x) => x.toJson())),
      };
}

class StateNames {
  StateNames({
    this.stateName,
  });

  String stateName;

  factory StateNames.fromJson(Map<String, dynamic> json) => StateNames(
        stateName: json["state_name"],
      );

  Map<String, dynamic> toJson() => {
        "state_name": stateName,
      };
}
question from:https://stackoverflow.com/questions/65661909/cant-decode-parse-json-type-liststring-with-this-liststring-type-model-in-d

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can copy paste run full code below
In working demo, simulate network delay with 3 seconds
You can use FutureBuilder and use return countryDetailsModelFromJson(jsonString);
code snippet

Future<List<CountryDetailsModel>> getHttp() async {
    String jsonString = ...

    return countryDetailsModelFromJson(jsonString);
}
...  
FutureBuilder(
            future: _future,
            builder:
                (context, AsyncSnapshot<List<CountryDetailsModel>> snapshot) {
              ...
                    return DropdownButton<CountryDetailsModel>(
                      //isDense: true,
                      hint: Text('Choose'),
                      value: _selectedValue,
                      icon: Icon(Icons.check_circle_outline),
                      iconSize: 24,
                      elevation: 16,
                      style: TextStyle(color: Colors.deepPurple),
                      underline: Container(
                        height: 2,
                        color: Colors.blue[300],
                      ),
                      onChanged: (CountryDetailsModel newValue) {
                        setState(() {
                          _selectedValue = newValue;
                        });
                      },
                      items: snapshot.data
                          .map<DropdownMenuItem<CountryDetailsModel>>(
                              (CountryDetailsModel value) {
                        return DropdownMenuItem<CountryDetailsModel>(
                          value: value,
                          child: Text(value.countryName),
                        );
                      }).toList(),
                    );
                  }
              }
            })

working demo

enter image description here

full code

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

List<CountryDetailsModel> countryDetailsModelFromJson(String str) =>
    List<CountryDetailsModel>.from(
        json.decode(str).map((x) => CountryDetailsModel.fromJson(x)));

String countryDetailsModelToJson(List<CountryDetailsModel> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class CountryDetailsModel {
  CountryDetailsModel({
    this.countryName,
    this.alpha2Code,
    this.countryCode,
    this.states,
  });

  String countryName;
  String alpha2Code;
  String countryCode;
  List<StateNames> states;

  factory CountryDetailsModel.fromJson(Map<String, dynamic> json) =>
      CountryDetailsModel(
        countryName: json["country_name"],
        alpha2Code: json["alpha2_code"],
        countryCode: json["country_code"],
        states: List<StateNames>.from(
            json["states"].map((x) => StateNames.fromJson(x))),
      );

  Map<String, dynamic> toJson() => {
        "country_name": countryName,
        "alpha2_code": alpha2Code,
        "country_code": countryCode,
        "states": List<dynamic>.from(states.map((x) => x.toJson())),
      };
}

class StateNames {
  StateNames({
    this.stateName,
  });

  String stateName;

  factory StateNames.fromJson(Map<String, dynamic> json) => StateNames(
        stateName: json["state_name"],
      );

  Map<String, dynamic> toJson() => {
        "state_name": stateName,
      };
}

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

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: MyStatefulWidget(),
      ),
    );
  }
}

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

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

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  CountryDetailsModel _selectedValue;
  Future<List<CountryDetailsModel>> _future;

  Future<List<CountryDetailsModel>> getHttp() async {
    String jsonString = '''
    [
  {
    "country_name": "Andorra",
    "alpha2_code": "AD",
    "country_code": "376",
    "states": [
      { "state_name": "Andorra la Vella" },
      { "state_name": "Canillo" },
      { "state_name": "Encamp" },
      { "state_name": "La Massana" },
      { "state_name": "Les Escaldes" },
      { "state_name": "Ordino" },
      { "state_name": "Sant Julia de Loria" }
    ]
  },
  {
    "country_name": "Azerbaijan",
    "alpha2_code": "AZ",
    "country_code": "994",
    "states": [
      { "state_name": "Abseron" },
      { "state_name": "Baki Sahari" },
      { "state_name": "Ganca" },
      { "state_name": "Ganja" },
      { "state_name": "Kalbacar" },
      { "state_name": "Lankaran" },
      { "state_name": "Mil-Qarabax" },
      { "state_name": "Mugan-Salyan" },
      { "state_name": "Nagorni-Qarabax" },
      { "state_name": "Naxcivan" },
      { "state_name": "Priaraks" },
      { "state_name": "Qazax" },
      { "state_name": "Saki" },
      { "state_name": "Sirvan" },
      { "state_name": "Xacmaz" }
    ]
  }]
    ''';

    return countryDetailsModelFromJson(jsonString);

  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder(
            future: _future,
            builder:
                (context, AsyncSnapshot<List<CountryDetailsModel>> 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 DropdownButton<CountryDetailsModel>(
                      //isDense: true,
                      hint: Text('Choose'),
                      value: _selectedValue,
                      icon: Icon(Icons.check_circle_outline),
                      iconSize: 24,
                      elevation: 16,
                      style: TextStyle(color: Colors.deepPurple),
                      underline: Container(
                        height: 2,
                        color: Colors.blue[300],
                      ),
                      onChanged: (CountryDetailsModel newValue) {
                        setState(() {
                          _selectedValue = newValue;
                        });
                      },
                      items: snapshot.data
                          .map<DropdownMenuItem<CountryDetailsModel>>(
                              (CountryDetailsModel value) {
                        return DropdownMenuItem<CountryDetailsModel>(
                          value: value,
                          child: Text(value.countryName),
                        );
                      }).toList(),
                    );
                  }
              }
            }));
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...