You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何同时返回嵌套JSON中的LocationData与MediaData并在FutureBuilder中使用

嵌套JSON数据同时获取LocationData与MediaData的实现方案

示例JSON结构

{
  "location": {
    "id": 1,
    "name": "Central Park",
    "address": "New York, NY"
  },
  "media": [
    {
      "id": 101,
      "url": "https://example.com/park1.jpg",
      "type": "image"
    },
    {
      "id": 102,
      "url": "https://example.com/park_video.mp4",
      "type": "video"
    }
  ]
}

模型代码

保留原有LocationData和MediaData模型,新增CombinedData模型包裹两类数据,并实现[]操作符支持Map式访问:

class LocationData {
  final int id;
  final String name;
  final String address;

  LocationData({required this.id, required this.name, required this.address});

  factory LocationData.fromJson(Map<String, dynamic> json) {
    return LocationData(
      id: json['id'],
      name: json['name'],
      address: json['address'],
    );
  }
}

class MediaData {
  final int id;
  final String url;
  final String type;

  MediaData({required this.id, required this.url, required this.type});

  factory MediaData.fromJson(Map<String, dynamic> json) {
    return MediaData(
      id: json['id'],
      url: json['url'],
      type: json['type'],
    );
  }
}

class CombinedData {
  final LocationData location;
  final List<MediaData> media;

  CombinedData({required this.location, required this.media});

  factory CombinedData.fromJson(Map<String, dynamic> json) {
    return CombinedData(
      location: LocationData.fromJson(json['location']),
      media: (json['media'] as List)
          .map((item) => MediaData.fromJson(item))
          .toList(),
    );
  }

  // 支持snapshot.data['media']/['location']的访问方式
  dynamic operator [](String key) {
    switch (key) {
      case 'location':
        return location;
      case 'media':
        return media;
      default:
        throw ArgumentError('Invalid key: $key');
    }
  }
}

API请求代码

使用http库请求并解析数据为CombinedData:

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

Future<CombinedData> fetchCombinedData() async {
  final response = await http.get(Uri.parse('https://your-api-endpoint.com/data'));

  if (response.statusCode == 200) {
    final jsonResponse = jsonDecode(response.body);
    return CombinedData.fromJson(jsonResponse);
  } else {
    throw Exception('Failed to load combined data');
  }
}

FutureBuilder页面代码

在页面中通过FutureBuilder获取并展示两类数据:

import 'package:flutter/material.dart';

class DataDisplayPage extends StatelessWidget {
  final Future<CombinedData> combinedDataFuture = fetchCombinedData();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Location & Media')),
      body: FutureBuilder<CombinedData>(
        future: combinedDataFuture,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // 展示Location数据
                  Text('地点: ${snapshot.data!['location'].name}', style: const TextStyle(fontSize: 18)),
                  Text('地址: ${snapshot.data!['location'].address}', style: const TextStyle(fontSize: 16)),
                  const SizedBox(height: 20),
                  const Text('媒体列表:', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                  // 遍历展示Media数据
                  Expanded(
                    child: ListView.builder(
                      itemCount: snapshot.data!['media'].length,
                      itemBuilder: (context, index) {
                        final mediaItem = snapshot.data!['media'][index];
                        return ListTile(
                          title: Text('类型: ${mediaItem.type}'),
                          subtitle: Text('链接: ${mediaItem.url}'),
                        );
                      },
                    ),
                  ),
                ],
              ),
            );
          } else if (snapshot.hasError) {
            return Center(child: Text('加载失败: ${snapshot.error}'));
          }
          // 加载状态
          return const Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
}

核心说明

  • 通过CombinedData模型统一解析嵌套的JSON结构,避免单独解析的繁琐
  • 实现operator[]让模型支持类似Map的键值访问,满足你要求的snapshot.data['media'][0].fieldname调用方式
  • FutureBuilder中直接通过键名访问对应数据集合,再调用模型字段展示内容

内容的提问来源于stack exchange,提问作者jamie1231

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:40:27