【问题标题】:Flutter Dart deserialize a json with dynamic key but structured values into Map<String, ModelClass>Flutter Dart 将具有动态键但结构化值的 json 反序列化为 Map<String, ModelClass>
【发布时间】:2020-01-18 10:52:01
【问题描述】:

是否可以将具有动态键但结构化值的 json 反序列化为 Flutter dart 中的 Map。

我有一个类似的 json

{
   "data" : {
            "apple":{"qty":5, "price":100},
            "orange":{"qty":2, "price":40},
           }
}

我希望它在 flutter/dart 中反序列化为下面的模型类

class Data {
    Map<String, Item> itemMap;

    factory Data.fromJson(Map<String,dynamic> json) {
        itemMap : json["data"]; //How to parse.
    }
}

class Item {
   int qty;
   int price;
}

我已经阅读了medium blog,即使这也没有涵盖地图部分。

【问题讨论】:

    标签: json flutter dart json-deserialization


    【解决方案1】:

    你需要做这样的事情:

    //...
    Future<List<ItemModel>> fetchFood() async {
    
        List<ItemModel> foodItemsList = [];
    
        // Get json response and parse it as a Map<String, dynamic>
        final response = {
           "data" : {
                "apple":{"qty":5, "price":100},
                "orange":{"qty":2, "price":40},
               }
           };
        // with your real get request use this:
        // final parsedJson = json.decode(response.body)['data'];
    
        // Parsed Json have what's inside data, in case of real request look for the line above this.
        final parsedJson = response['data'];
    
        // Iterate over all fruits and create Item object from each,
        // then push to a list of Item's objects to return it.
        parsedJson.forEach((k,v) => foodItemsList.add(ItemModel.fromJson(v)));
    
        return foodItemsList;
    }
    
    // Item model
    class ItemModel {
       int qty;
       int price;
    
       ItemModel.fromJson(Map<String,dynamic> parsedJson)
          : qty = parsedJson['qty'],
            price = parsedJson['price'];
    
    }
    
    // Then call it
    main() async {
    
      List<ItemModel> foodItemsList = await fetchFood();
      //..
    }
    
    

    如果您需要水果名称作为对象的一部分

    //...
    Future<List<ItemModel>> fetchFood() async {
    
        List<ItemModel> foodItemsList = [];
    
        // Get json response and parse it as a Map<String, dynamic>
        final response = {
           "data" : {
                "apple":{"qty":5, "price":100},
                "orange":{"qty":2, "price":40},
               }
           };
        // with your real get request use this:
        // final parsedJson = json.decode(response.body)['data'];
    
        // Parsed Json have what's inside data, in case of real request look for the line above this.
        final parsedJson = response['data'];
    
        // Iterate over all fruits and create Item object from each,
        // then push to a list of Item's objects to return it.
        parsedJson.forEach((fruitName, fruitDetails) 
            => foodItemsList.add(
                 ItemModel.fromJson(fruitName, fruitDetails)
            )
        );
    
        return foodItemsList;
    }
    
    // Item model
    class ItemModel {
       String name;
       int qty;
       int price;
    
       ItemModel.fromJson(String fruitName, Map<String,dynamic> parsedJson)
          : name = fruitName,
            qty = parsedJson['qty'],
            price = parsedJson['price'];
    
    }
    
    // Then call it
    main() async {
    
      List<ItemModel> foodItemsList = await fetchFood();
      print(foodItemsList[1].name); //orange
      //..
    }
    
    

    【讨论】:

    • 这里的键是动态的,你不知道水果的名字!
    • @YudhishthirSingh 是的,我是通过循环response['data'] 得到名字的,然后fruitName 将是response['data'].forEach((fruitName, fruitDetails) =&gt; ...); 的每个项目的键,类似于response['data'].forEach((key, value)=&gt; ...);
    • 如何让方法等待将数据添加到列表中。在我的代码中,在我将数据添加到列表之前执行返回。如何让它等待 forEach() 执行?
    【解决方案2】:

    我有一个类似的 JSON,但有一些变化:

    {
      "sub_item": {
        "491": ["92837|1.3|Pistachio|right", "92838|2.5|Hazelnut|left"],
        "427": ["92839|7.05|Almonds|", "92840|5.12|Walnuts|"],
        "396": ["92841|15|Saffron|"],
        "275": ["92842|45|Caviar|"]
      }
    }
    

    sub_item 映射的键(491427396275 和.. .) 是动态的(作为标签而不是类型)并且会根据订单而改变。例如,它将是 376、325、493... 以另一个顺序。

    我想在我的 Flutter 应用上同时显示键和值,但不知道如何获取这些数据并分别显示它们。像这样的:

    491:
    £1.30  Pistachio
    £2.50  Hazelnut
    
    427:
    £7.05  Almonds
    £5.12  Walnuts
    
    396:
    £15.00 Saffron
    
    275:
    £45.00 Caviar
    

    我使用了这段代码,它以某种方式对我有用,但它只显示列表的第一项。例如,它仅显示 491 的 Pistachio 而不是 Hazelnut,同样它仅显示 427 的 Almonds 而不是 Walnuts

    Future<List<ItemModel>> fetchFood() async {
      List<ItemModel> foodItemsList = [];
    
      final response = {
        "sub_item": {
          "491": ["92837|1.3|Pistachio|right", "92838|2.5|Hazelnut|left"],
          "427": ["92839|7.05|Almonds|", "92840|5.12|Walnuts|"],
          "396": ["92841|15|Saffron|"],
          "275": ["92842|45|Caviar|"]
        }
      };
    
      final parsedJson = response['sub_item'];
    
      parsedJson.forEach((fruitName, fruitDetails) =>
          foodItemsList.add(ItemModel.fromJson(fruitName, fruitDetails)));
    
      return foodItemsList;
    }
    
    // Item model
    class ItemModel {
      String id;
      String details;
    
      ItemModel.fromJson(String subItemID, List<dynamic> subItemDetails)
          : id = subItemID,
            details = subItemDetails[0];
    }
    
    // Then call it
    mainTest() async {
      List<ItemModel> foodItemsList = await fetchFood();
      for (var i = 0, j = 0;
          i < foodItemsList.length;
          j < foodItemsList[i].details.length, i++, j++) {
        print(foodItemsList[i].id);
        print(foodItemsList[j].details.split('|')[2]);
      }
    }
    

    控制台结果:

    flutter: 491
    flutter: Pistachio
    flutter: 427
    flutter: Almonds
    flutter: 396
    flutter: Saffron
    flutter: 275
    flutter: Caviar
    

    【讨论】:

      【解决方案3】:

      我找到了实现它的方法。我们可以将 Map 从一种类型转换为另一种类型。

      class Data {
          Map<String, Item> itemMap;
      
          factory Data.fromJson(Map<String,dynamic> json) {
              itemMap : getMapDataFrom(json["data"]); //How to parse.
          }
      
          static Map<String, Item> getFruitItemMap(Map<String, dynamic> map) {
             final Map<String, Item> fruitItemMap = HashMap();
             map.forEach((name, value) {
                 bitItemLites[name] = Item.fromJson(value, name);
             });
      
             return bitItemLites;
          }
      }
      
      class Item {
         int qty;
         int price;
      
         factory Item.fromJson(Map<String,dynamic> json) {
            return Item(json['qty'], json['price']);
         }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-08-20
        • 2021-01-26
        • 2020-08-25
        • 1970-01-01
        • 2020-11-13
        • 1970-01-01
        • 1970-01-01
        • 2017-01-24
        • 1970-01-01
        相关资源
        最近更新 更多