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

Dart:无需JSON往返转换生成oauth2.Credentials列表

Dart OAuth2 Credentials.fromJson 冗余JSON往返问题解决

问题场景

实现基于JSON文件的多凭证存储时,直接使用已解析的JSON Map调用Credentials.fromJson()会触发类型错误,必须先将Map重新编码为JSON字符串再传入才能正常运行,这种方式冗余且不够优雅。

原始代码

import 'dart:convert';
import 'dart:io';
import 'package:oauth2/oauth2.dart';

class CredentialStore {
  List<Credentials> get credentials {
    // credentials.json 存储通过 oauth2.Credentials.toJson() 生成的对象数组
    final file = File('credentials.json');
    final jsonString = file.readAsStringSync();
    final List cred = jsonDecode(jsonString);
    return List<Credentials>.from(cred.map((e) => Credentials.fromJson(e)));
  }
}

运行时错误

Unhandled exception:
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'

临时冗余解决方案

将已解析的Map重新编码为JSON字符串后传入,代码可正常运行:

return List<Credentials>.from(cred.map((e) => Credentials.fromJson(jsonEncode(e))));

原因分析与优化方案

原因

Credentials.fromJson()的参数设计确实只接受JSON字符串,而非已解析的Map对象。该方法内部会自行执行JSON解码操作,直接传入Map会导致类型不匹配错误。

优化方案

如果想避免冗余的JSON往返转换,可采用以下两种方式:

  1. 手动构造Credentials对象
    直接从Map中提取对应字段创建对象,完全避免重复编解码:
return cred.map((map) {
  return Credentials(
    map['accessToken'],
    refreshToken: map['refreshToken'],
    idToken: map['idToken'],
    tokenEndpoint: Uri.parse(map['tokenEndpoint']),
    scopes: List<String>.from(map['scopes'] ?? []),
    expiration: map['expiration'] != null ? DateTime.fromMillisecondsSinceEpoch(map['expiration']) : null,
  );
}).toList();

注意字段名必须与Credentials.toJson()输出的字段完全一致,同时要处理空值场景。

  1. 封装转换工具方法
    如果需要多次使用,可封装一个复用性方法:
Credentials credentialsFromMap(Map<String, dynamic> map) {
  return Credentials(
    map['accessToken'],
    refreshToken: map['refreshToken'],
    idToken: map['idToken'],
    tokenEndpoint: Uri.parse(map['tokenEndpoint']),
    scopes: List<String>.from(map['scopes'] ?? []),
    expiration: map['expiration'] != null ? DateTime.fromMillisecondsSinceEpoch(map['expiration']) : null,
  );
}

// 在getter中调用
return cred.map((e) => credentialsFromMap(e)).toList();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:27:31