如果将来添加任何键,json如何解析动态键和值

Posted

技术标签:

【中文标题】如果将来添加任何键,json如何解析动态键和值【英文标题】:How json parse dynamic key and value in flutter if any key added in future 【发布时间】:2021-06-19 20:24:17 【问题描述】:

我在最初获得不同形状属性的地方得到响应。


    "success": true,
    "data": 
         "pcode": "001",
         "pname": "ABC",
         "pprice": "100"
        "ones": [
                "id": "2",
                "username": "LM10002"
            ,
            
                "id": "6",
                "username": "LM10006"
            
        ],
        "twos": [
                "id": "3",
                "username": "LM10003"
            ,
            
                "id": "8",
                "username": "LM10008"
            
        ],
        ]
    

这里的 "ones","twos" .. 是动态键,将来还会添加新数组。 所以我们可以在 Flutter 中动态管理它?

【问题讨论】:

【参考方案1】:

我的第一个建议是使用数字而不是字符串来转换这些数据,因此无论将来标签(onestwos 等)是否发生变化,都不会影响您的代码:

void main() 
  final data =  
    "success": true, 
    "data":  
      "ones": [
         "id": "2", "username": "LM10002" , 
         "id": "6", "username": "LM10006"  
      ], 
      "twos": [
         "id": "3", "username": "LM10003" , 
         "id": "8", "username": "LM10008"  
      ] 
    
  ;

  print(ApiResponse.fromJson(data));


class ApiResponse 
  final bool success;
  final List<List<Data>> data; 
  
  ApiResponse(this.success, this.data);
  
  factory ApiResponse.fromJson(Map<String, dynamic> json) 
    
    List<List<Data>> dataList = [];
    final jsonData = (json["data"] as Map<String, dynamic>);
    jsonData.values.forEach((value) 
      List<Data> parsedList = List<Data>.from(List.from(value).map((element) => Data.fromJson(element)));
      dataList.add(parsedList);
    );
      
    return ApiResponse(
      success: json["success"],
      data: dataList,
    );
  
  

  @override
  String toString() 
     return "Success: $success, Data: $data.map((element) => element.map((d) => "$d.id $d.username")).toList().join("; ")";
  


class Data 
  final String id;
  final String username;
  
  Data(this.id, this.username);
  
  factory Data.fromJson(Map<String, dynamic> json) 
    return Data(
      id: json["id"],
      username: json["username"],
    );
  

这应该返回一个数据列表,其中每个index+1 将代表顺序(一个或两个等...),附加的值将直接是数据列表。

主函数中的打印语句将打印这个:Success: true, Data: (2 LM10002, 6 LM10006); (3 LM10003, 8 LM10008)

第二种方法是为您的每个数据添加一个group 属性,以便您知道每个数据属于哪个组(ones、twos 等...)

这是完整的实现:

void main() 
  final data =  
    "success": true, 
    "data":  
      "ones": [
         "id": "2", "username": "LM10002" , 
         "id": "6", "username": "LM10006"  
      ], 
      "twos": [
         "id": "3", "username": "LM10003" , 
         "id": "8", "username": "LM10008"  
      ] 
    
  ;

  print(ApiResponse.fromJson(data));


class ApiResponse 
  final bool success;
  final List<Data> data; 
  
  ApiResponse(this.success, this.data);
  
  factory ApiResponse.fromJson(Map<String, dynamic> json) 
    
    List<Data> dataList = [];
    final jsonData = (json["data"] as Map<String, dynamic>);
    jsonData.forEach((key, value) 
      List<Data> parsedList = List<Data>.from(List.from(value).map((element)  
        element["group"] = key;
        return Data.fromJson(element);
      ));
      dataList.addAll(parsedList);
    );
      
    return ApiResponse(
      success: json["success"],
      data: dataList,
    );
  

  @override
  String toString() 
     return "Success: $success, Data: $data.map((element) => "$element.id, $element.username, $element.group")";
  


class Data 
  final String id;
  final String username;
  final String group;
  
  Data(this.id, this.username, this.group);
  
  factory Data.fromJson(Map<String, dynamic> json) 
    return Data(
      id: json["id"],
      username: json["username"],
      group: json["group"]
    );
  

main 方法中的 print 语句应该打印:Success: true, Data: (2, LM10002, ones, 6, LM10006, ones, 3, LM10003, twos, 8, LM10008, twos)

总结一下:

Solution Description Advantage Disadvantage
#1 Proposes to represent the data in the form of a matrix with in ordinates the indexes-1 of the "groups" of data, and in abcissa, the data themselves We keep the order of the data and it is easy to sort them Not great for readability, and the group labels returned by the API are
#2 Allows to keep the labels as strings and add them to the data (to later filter the data automatically according to the groups) We keep the initial data group labels It will be more difficult to perform sorting

【讨论】:

这很好,但是如何访问这个字段。 “pcode”:“001”,“pname”:“ABC”,“pprice”:“100”这些是修复。 这会很棘手。我会建议您在将数据发送回前端之前更好地格式化后端的数据。为每次调用向前端发送相同的数据格式会更容易、更清晰。【参考方案2】:

您可以创建一个类来处理这种响应。您将能够访问分配给数据键的映射的不同键并对其执行任何您想要的操作。

class CustomResponse 
  bool success;
  Map<String, dynamic> data;
  
  CustomResponse(this.success, this.data);
  
  factory CustomResponse.fromJson(Map json) 
    return CustomResponse(
      json['success'] as bool,
      json['data'] as Map<String, dynamic>,
    );    
  


void main()  
  final data =  
    "success": true, 
    "data":  
      "ones": [
         "id": "2", "username": "LM10002" , 
         "id": "6", "username": "LM10006"  
      ], 
      "twos": [
         "id": "3", "username": "LM10003" , 
         "id": "8", "username": "LM10008"  
      ] 
    
  ;
  
  final customResponse =  CustomResponse.fromJson(data);
  print(customResponse.data.keys);  

【讨论】:

如果响应不同怎么办?据我了解,他可以有两个回应,或者没有回应,或者有两个,三个等等......我认为你的解决方案在这些情况下是不够的

以上是关于如果将来添加任何键,json如何解析动态键和值的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用 Scala-Play Json 框架解析 Json 时获取键和值?

如何将这样的 JSON 解析为 NSDictionary 并获取键和值

使用动态键和值动态创建 JSON

如何在 ngFor 中显示一个简单 json 的所有键和值? [复制]

JSON路径抓取键和值

如何从嵌套 Json 数组角度 2 打印和分离键和值并将其添加到选择框中