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

Flutter嵌套JSON解析求助:值为字符串列表的键值对处理

Flutter解析嵌套JSON并提取字符串列表的简单方法

首先注意到你的API返回的是JSONP格式(被callback()包裹),不是标准JSON,这是第一步要处理的核心点。下面是最直接的实现方案:

1. 预处理响应字符串

先剥离包裹在外的callback(和),得到标准JSON字符串:

// 假设responseBody是从API获取的原始响应内容
String pureJson = responseBody.replaceFirst(RegExp(r'^callback\('), '').replaceFirst(RegExp(r'\)$'), '');

2. 解码JSON并提取目标列表

用Dart内置的dart:convert包解码,逐层访问嵌套字段直接取出字符串列表:

import 'dart:convert';

// 解码JSON为Map
Map<String, dynamic> decodedJson = jsonDecode(pureJson);

// 提取compound对应的字符串列表
List<String> compoundList = List<String>.from(decodedJson['dictionary_terms']['compound']);

3. 完整示例(结合TypeAhead组件)

如果使用flutter_typeahead组件,结合网络请求的完整代码如下:

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

// 从API获取数据的方法
Future<List<String>> fetchCompoundList() async {
  final response = await http.get(Uri.parse('你的API接口地址'));
  
  if (response.statusCode == 200) {
    // 处理JSONP格式
    String pureJson = response.body.replaceFirst(RegExp(r'^callback\('), '').replaceFirst(RegExp(r'\)$'), '');
    Map<String, dynamic> decodedJson = jsonDecode(pureJson);
    return List<String>.from(decodedJson['dictionary_terms']['compound']);
  } else {
    throw Exception('数据请求失败');
  }
}

// 集成TypeAhead的Widget
class CompoundAutoComplete extends StatefulWidget {
  @override
  _CompoundAutoCompleteState createState() => _CompoundAutoCompleteState();
}

class _CompoundAutoCompleteState extends State<CompoundAutoComplete> {
  late Future<List<String>> _compoundListFuture;

  @override
  void initState() {
    super.initState();
    _compoundListFuture = fetchCompoundList();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<String>>(
      future: _compoundListFuture,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return TypeAheadField(
            suggestionsCallback: (pattern) {
              // 根据输入关键词过滤列表
              return snapshot.data!.where((item) => item.toLowerCase().contains(pattern.toLowerCase())).toList();
            },
            itemBuilder: (context, suggestion) {
              return ListTile(title: Text(suggestion));
            },
            onSuggestionSelected: (suggestion) {
              // 选中选项后的逻辑
              print('已选择: $suggestion');
            },
          );
        } else if (snapshot.hasError) {
          return Text('加载失败: ${snapshot.error}');
        }
        return CircularProgressIndicator();
      },
    );
  }
}

关于JSON Serializable的补充

如果一定要用JSON Serializable,只需正确定义嵌套模型即可,示例如下:

import 'package:json_annotation/json_annotation.dart';

part 'api_response.g.dart';

@JsonSerializable()
class ApiResponse {
  Status status;
  int total;
  DictionaryTerms dictionary_terms;

  ApiResponse({required this.status, required this.total, required this.dictionary_terms});

  factory ApiResponse.fromJson(Map<String, dynamic> json) => _$ApiResponseFromJson(json);
  Map<String, dynamic> toJson() => _$ApiResponseToJson(this);
}

@JsonSerializable()
class Status {
  int code;

  Status({required this.code});

  factory Status.fromJson(Map<String, dynamic> json) => _$StatusFromJson(json);
  Map<String, dynamic> toJson() => _$StatusToJson(this);
}

@JsonSerializable()
class DictionaryTerms {
  List<String> compound;

  DictionaryTerms({required this.compound});

  factory DictionaryTerms.fromJson(Map<String, dynamic> json) => _$DictionaryTermsFromJson(json);
  Map<String, dynamic> toJson() => _$DictionaryTermsToJson(this);
}

运行flutter pub run build_runner build生成序列化代码后,同样先处理JSONP字符串,再通过ApiResponse.fromJson(jsonDecode(pureJson))解析,最终取出apiResponse.dictionary_terms.compound即可。

不过如果只是为了提取这个字符串列表,手动解码的方式更简单直接,无需额外依赖和代码生成步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:35:21