简体   繁体   English

如何根据相同的字符串值显示第 2 个 JSON 的数据

[英]How to show data from 2nd JSON based on the same value of String

I have 2 JSON file:我有 2 JSON 文件:

country.json国家.json

[
  {
    "countryName": "United States",
    "countryContinent": "North America"
  },
  {
    "countryName": "Germany",
    "countryContinent": "Europe"
  },
  {
    "countryName": "United Kingdom",
    "countryContinent": "Europe"
  }
]

continent.json大陆.json

[
  {
    "continentName": "North America",
    "continentCountry": [
      "Canada",
      "Mexico",
      "Cuba"
    ],
    "continentArea": 24790000,
    "continentFlag": [
      "https://www.countryflags.io/ca/shiny/64.png",
      "https://www.countryflags.io/mx/shiny/64.png",
      "https://www.countryflags.io/cu/shiny/64.png"
    ]
  },
  {
    "continentName": "Europe",
    "continentCountry": [
      "Denmark",
      "Finland",
      "France"
    ],
    "continentArea": 10180000,
    "continentFlag": [
      "https://www.countryflags.io/dk/shiny/64.png",
      "https://www.countryflags.io/fi/shiny/64.png",
      "https://www.countryflags.io/fr/shiny/64.png"
    ]
  }
]

I want to build a list based on country.json, then for each value of countryContinent that == value of continentName => show data of value continentCountry from continent.json like this我想建立一个基于 country.json 的列表,然后对于countryContinent的每个值 == continentName的值 => 显示来自 continent.json 的值continentCountry的数据,就像这样

在此处输入图像描述

So pls help me, this is main file:所以请帮助我,这是主文件:

import 'package:ask/model/continent_model.dart';
import 'package:ask/model/country_model.dart';
import 'package:ask/services/continent_services.dart';
import 'package:ask/services/country_service.dart';
import 'package:flutter/material.dart';

class Demo2 extends StatefulWidget {
  Demo2() : super();
  @override
  _Demo2State createState() => _Demo2State();
}

class _Demo2State extends State<Demo2> {
  List<Country> _country = [];
  List<Continent> _continent = [];

  @override
  void initState() {
    super.initState();
    CountryServices.getCountry().then((countries) {
      setState(() {
        _country = countries;
      });
    });
    ContinentServices.getContinent().then((continents) {
      setState(() {
        _continent = continents;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Demo 2')),
        body: Column(
          children: <Widget>[
            for (Country country in _country)
              Row(
                children: <Widget>[
                  Expanded(child: Text(country.countryName)),
                  Expanded(child: Text(country.countryContinent)),
                  Expanded(child: Text('')), // How to show data of continentCountry
                ],
              )
          ],
        ));
  }
}


EDIT 2:编辑 2:

To avoid creating another post, I extend the following question: in continent.json, there is more data about continentCountry ("Greenland"; "Panama"; "Jamaica") that matches the value of continentName ("North America") like this:为了避免创建另一个帖子,我扩展了以下问题:在 continent.json 中,有更多关于continentCountry ("Greenland"; "Panama"; "Jamaica") 的数据与continentName ("North America") 的值匹配,如下所示:

continent.json (edit 2) continent.json(编辑2)

[
  {
    "continentName": "North America",
    "continentArea": "Area1",
    "continentCountry": [
      "Canada",
      "Mexico",
      "Cuba"
    ],
    "continentFlag": [
      "https://www.countryflags.io/ca/shiny/64.png",
      "https://www.countryflags.io/mx/shiny/64.png",
      "https://www.countryflags.io/cu/shiny/64.png"
    ]
  },
  {
    "continentName": "North America",
    "continentArea": "Area2",
    "continentCountry": [
      "Greenland",
      "Panama",
      "Jamaica"
    ],
    "continentFlag": [
      "https://www.countryflags.io/gl/shiny/64.png",
      "https://www.countryflags.io/pa/shiny/64.png",
      "https://www.countryflags.io/jm/shiny/64.png"
    ]
  },
  {
    "continentName": "Europe",
    "continentArea": "Area3",
    "continentCountry": [
      "Denmark",
      "Finland",
      "France"
    ],
    "continentFlag": [
      "https://www.countryflags.io/dk/shiny/64.png",
      "https://www.countryflags.io/fi/shiny/64.png",
      "https://www.countryflags.io/fr/shiny/64.png"
    ]
  },
  {
    "continentName": "Asia",
    "continentArea": "Area4",
    "continentCountry": [
      "Japan"
    ],
    "continentFlag": [
      "https://www.countryflags.io/jp/shiny/64.png"
    ]
  }
]

so I want to display all of the continentCountry of "North America" as follows:所以我想显示“北美”的所有continentCountry国家,如下所示: 在此处输入图像描述

Pls help请帮忙

you can loop over the list of strings List<String> in an seperate function like List<Text> getSameContinentCountries .您可以在单独的 function 中遍历字符串List<String> ,例如List<Text> getSameContinentCountries

class for data representation class 用于数据表示

Country国家

class Country {
  String countryName;
  String countryContinent;

  Country({this.countryName, this.countryContinent});

  factory Country.fromJson(Map<String, dynamic> json) {
    return Country(
      countryName: json['countryName'],
      countryContinent: json['countryContinent'],
    );
  }
}

Continent大陆

class Continent {
  String continentName;
  List<String> continentCountry;

  Continent({this.continentName, this.continentCountry});

  factory Continent.fromJson(Map<String, dynamic> json) {
    return Continent(
      continentName: json['continentName'],
      continentCountry: json['continentCountry'],
    );
  }
}

You can now generate the List<Country> _country and List<Continent> _continent in the initState with:您现在可以在 initState 中生成List<Country> _countryList<Continent> _continent

// TODO generate Lists
    for (Map<String, dynamic> _json in continentListResponse) {
      continent2 = Continent.fromJson(_json);
      this._continent.add(continent2);
    }
    for (Map<String, dynamic> _json in countryListResponse) {
      country2 = Country.fromJson(_json);
      this._country.add(country2);
    }

function for Countries in Continents function 大陆国家

Text only纯文本

List<Text> getSameContinentCountries({@required String countryContinent}) {
    int continentIndex = this
        ._continent
        .indexWhere((continent) => continent.continentName == countryContinent);
    List<String> _cC = this._continent[continentIndex].continentCountry;
    List<Text> wrapText = [Text('no Countries found')];
    if (_cC.length > 0) {
      wrapText = [];
      for (String country in _cC) {
        wrapText.add(Text(country));
      }
    }
    return wrapText;
  }

all widgets所有小部件

List<Widget> getSameContinentCountries({@required String countryContinent}) {
    // returns a List of any Widget, many combinations possible
    // such as chips, cards etc.
    int continentIndex = this
        ._continent
        .indexWhere((continent) => continent.continentName == countryContinent);
    List<String> _cC = this._continent[continentIndex].continentCountry;
    List<Widget> wrapText = [Text('no Countries found')];
    if (_cC.length > 0) {
      wrapText = [];
      for (String country in _cC) {
        // you may want to use Padding
        wrapText.add(Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: Text(country),
        ));
        // simple | divider with Text widget
        wrapText.add(Padding(
          padding: const EdgeInsets.symmetric(horizontal: 2),
          child: Text('|'),
        ));
        // or use the VerticalDivider which needs a parent with height
        wrapText.add(
          Container(
              height: 15,
              child: VerticalDivider(
                color: Colors.red,
                width: 4,
                thickness: 2,
              )),
        );
        // or use any other widget, eg. chips
        wrapText.add(Chip(
          label: Text(country),
        ));
      }
    }
    // remove the last "divider"
    wrapText.removeLast();
    return wrapText;
  }

use function generated widget使用 function 生成的小部件

Here I would suggest you to use the Wrap Widget.在这里,我建议您使用Wrap Widget。

@override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('Demo 2')),
        body: Column(
          children: <Widget>[
            for (Country country in _country)
              Row(
                children: <Widget>[
                  Expanded(child: Text(country.countryName)),
                  Expanded(child: Text(country.countryContinent)),
                  Expanded(
                    child: Wrap(
                        children: getSameContinentCountries(
                            countryContinent: country.countryContinent)),
                  ),
                ],
              )
          ],
        ));
  }

Link to the result Image链接到结果图片

UPDATE更新

I can't comment on another answer yet, so I have to include this short info in my answer.我还不能评论另一个答案,所以我必须在我的答案中包含这个简短的信息。

To use the images, just return an Image widget, you may want to wrap it in a Sized Box or an Button / GestureDetctor for click events.要使用图像,只需返回一个 Image 小部件,您可能希望将它包装在一个Sized Box或一个Button / GestureDetctor中用于点击事件。

List<Widget> getFlags({@required String countryContinent}) {
    // returns a List of any Widget, many combinations possible
    // such as chips, cards, images, buttons etc.
    int continentIndex = this
        ._continent
        .indexWhere((continent) => continent.continentName == countryContinent);
    List<String> _cF = this._continent[continentIndex].continentFlag;
    List<Widget> wrapWidget = [Text('no Countries found')];
    if (_cF.length > 0) {
      wrapWidget = [];
      for (String flag in _cF) {
        // add the Flags
        wrapWidget.add(Image.network(flag));
      }
    }
    return wrapWidget;
  }

Result:结果:

旗帜

UPDATE 2更新 2

To have access to all flags with the same continentName , you have to extract the matching elemtens and then loop over the new List<Continent> .要访问具有相同continentName的所有标志,您必须提取匹配的元素,然后遍历新的List<Continent> Change the code of the getFlags function like so:像这样更改getFlags function 的代码:

List<Widget> getFlags({@required String countryContinent}) {
  // returns a List of any Widget, many combinations possible
  // such as chips, cards, images, buttons etc.
  //! UPDATE
  List<Continent> sameContient = this
      ._continent
      .where((continent) => continent.continentName == countryContinent)
      .toList();
  List<String> _cF = [];
  for (Continent sc in sameContient) {
    for (String flag in sc.continentFlag) {
      _cF.add(flag);
    }
  }
  List<Widget> wrapWidget = [Text('no Countries found')];
  if (_cF.length > 0) {
    wrapWidget = [];
    for (String flag in _cF) {
      // add the Flags
      wrapWidget.add(
          Image.network(flag, height: 16, width: 25, fit: BoxFit.contain));
    }
  }
  return wrapWidget;
}

and you will get the following result:你会得到以下结果: 在此处输入图像描述

Expanded(
   child: MyCountries(
     continent: List<Continent>.from(_continent)..retainWhere((continent) => 
       continent.continentName == country.countryContinent)
),

I create a widget MyCountries that receives a List, first I create a copy of that list (List.from) to avoid changing the original list _continent.我创建了一个接收列表的小部件 MyCountries,首先我创建了该列表的副本 (List.from) 以避免更改原始列表 _continent。 RetainWhere keeps only the elements that sastisfy the condition. RetainWhere 只保留满足条件的元素。 You wanted to keep only the continent where countryContinent == continentName您只想保留 countryContinent == continentName 所在的大陆

continent.continentName == country.countryContinent

and in the Mycountries widget在我的国家小部件中

class MyCountries extends StatelessWidget{
  final String countries;


  MyCountries({List<Continent> continent}) :
    this.countries = continent.reduce((prev, curr) => 
     prev..continentCountry.addAll(curr.continentCountry)).continentCountry.join(' | ');

  @override
  Widget build(BuildContext context) {
    return Text(countries);
  }
}

it gets the continent List and reduce it to a single continent object with a continentCountry List with all the countries, then just apply continentCountry.join(' | ') to join all the Strings of that list and create your countries String that you will use in the Text widget它获取大陆列表并将其缩减为单个大陆 object 以及包含所有国家/地区的大陆国家/地区列表,然后只需应用continentCountry.join(' | ')加入该列表的所有字符串并创建您将使用的国家/地区字符串在文本小部件中

UPDATE更新

From what I understand of your comments there should only be one ocurrence countryContinent that == value of continentName, I thought there could be more (my bad), so maybe you should change it like this根据我对您的评论的理解,应该只有一个 countryContinent == continentName 的值,我认为可能会有更多(我的坏),所以也许您应该像这样更改它

Expanded(
 child: MyArea(
 continent: _continent.firstWhere((continent) =>  continent.continentName == country.countryContinent)
 //This should return the first ocurrence, only one continent object
),

class MyArea extends StatelessWidget{
  final String area;

  MyArea({Continent continent}) :
    this.area = continent.continentArea.toString(); //You need to give a string to the Text widget anyway

  @override
  Widget build(BuildContext context) {
    return Text(area);
  }
}

I suppose List is a list of urls of the flags我想 List 是标志的 url 列表

Expanded(
 child: MyFlags(
 continent: _continent.firstWhere((continent) =>  continent.continentName == country.countryContinent)
 //This should return the first ocurrence, only one continent object
),

class MyFlags extends StatelessWidget{
  final List<String> flags;

  MyFlags ({Continent continent}) :
    this.flags= continent.continentFlag;

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, //or try other alignments or using Spacer() between widget in children
      children: [
        for(String flag in flags)
         Image.network(flag, height: 16, width: 25, fit: BoxFit.contain)
         //A flag is wider thatn taller, but you could try other sizes if you want 
      ]
    );
  }
}

UPDATE 2更新 2

Expanded(
 child: MyFlags(
 continent: List<Continent>.from(_continent)..retainWhere((continent) => 
       continent.continentName == country.countryContinent)
),

class MyFlags extends StatelessWidget{
  final List<String> flags;
  final List<String> countries;

  MyFlags ({List<Continent> continent}) :
    this.flags = continents.expand<String>((continent) => continent.continentFlag).toList(),
    this.countries = continents.expand<String>((continent) => continent.continentCountry).toList(),
    assert(flags.length == countries.length); //They should have the same length

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly, //or try other alignments or using Spacer() between widget in children
      children: [
        for(int i = 0; i < flags.length; i++)
         Column(
           children: [
             Image.network(flags[i], height: 16, width: 25, fit: BoxFit.contain),
             Text(countries[i])
           ]
         )
      ]
    );
  }
}

UPDATE 3更新 3

Expanded(
 child: MyFlags(
 continent: List<Continent>.from(_continent)..retainWhere((continent) => 
       continent.continentName == country.countryContinent)
),

class MyFlags extends StatelessWidget{
  final List<Continent> continent;

  MyFlags({this.continent});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        for(int i = 0; i < continent.length; i++)
          Row(
            children: [
              Text(continent[i].continentArea.toString()), // or 'Area ${i+1}' if you want to show Area 1, Area 2, etc
              for(String flag in continent[i].continentFlag)
                Image.network(flags[i], height: 16, width: 25, fit: BoxFit.contain),
            ]
          )
      ]
    );
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Flutter - 如何基于相同的值在单个 Json 文件中显示来自 2 个对象的数据 - Flutter - How to show data from 2 objects in single Json file based on the same value Flutter:如何根据Array的相同值显示来自2 JSON的数据 - Flutter: How to display data from 2 JSON based on the same value of Array 如何根据选择的第一项填充第二个下拉菜单 flutter - How to populating 2nd DropdownMenu based on first item selected flutter 将数据列表从一个屏幕传递到第二个屏幕 - passing a list of data from one screen to 2nd screen 是否可以使用 navigator.pop 刷新或重新加载页面...例如第 1(nav.push=&gt;2)页到第 2 页,然后从第 2(nav.pop,值)返回到第 1 页? - is it possible to refresh or reload page with navigator.pop... like 1st (nav.push=>2) page to 2nd page and back from 2nd (nav.pop, value) to 1st page? 我想在 flutter 中将数据从第二屏传递到第一屏 - I want to pass data from 2nd Screen to 1st Screen in flutter map 并发送 flutter 中第一页到第二页的数据列表 - map and send list of data from 1st to 2nd page in flutter 如何根据flutter中的下拉选择显示json数据? - how to show the json data based on the dropdown selection in flutter? 如何在 CupertinoPicker 中显示来自服务器的 json 数据 - How to show json data from server in CupertinoPicker 如何根据 Flutter 中的 DropdownMenuItem 选定值显示 REST API 数据? - How to show REST API data based on DropdownMenuItem selected value in flutter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM