我正在尝试使用Shelf 包和json_serializable处理 JSON 的一些代码。我有 2 个类和一个处理程序方法,如下所示(省略了错误处理)。
@freezed
abstract class User with _$User {
@JsonSerializable(explicitToJson: true)
factory User({
@required int id,
@JsonKey(name: 'USERNAME') @required String username,
@required String role,
}) = _User;
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
}
@freezed
abstract class _AddUserArgs with _$_AddUserArgs {
@JsonSerializable(explicitToJson: true)
factory _AddUserArgs({
@required User user,
}) = _AddUserArgs_Freezed;
factory _AddUserArgs.fromJson(Map<String, dynamic> json) =>
_$_AddUserArgsFromJson(json);
}
FutureOr<shelf.Response> _handleAddUser(
shelf.Request r,
) async {
try {
// Attempt to call service method.
final parsedJson = await r.readAsString();
final _AddUserArgs args = _AddUserArgs.fromJson(
jsonDecode(
parsedJson,
),
);
final AddUserResult result = await exampleService.addUser(
user: args.user,
);
return _rpcResp.Ok(
json: jsonEncode(
result.toJson(),
),
);
}
}
我遇到的并且我真的不太明白的问题是,每当这个端点被击中时,我都会不断收到以下错误。
type 'String' is not a subtype of type 'Map<String, dynamic>'
在尝试诊断错误时,我将 打印parsedJson
到控制台并直接粘贴到处理程序中,以尝试找出使用解析数据时 JSON 解析失败的原因,如下所示,并且它没有任何问题地工作。
try {
// Attempt to call service method.
final parsedJson = "{\"user\":{\"id\":0,\"USERNAME\":\"testuser\",\"role\":\"Kind.user()\"}}";
final _AddUserArgs args = _AddUserArgs.fromJson(
jsonDecode(
parsedJson,
),
);
final AddUserResult result = await exampleService.addUser(
user: args.user,
);
return _rpcResp.Ok(
json: jsonEncode(
result.toJson(),
),
);
}
我真的很困惑为什么会发生这种情况。我认为打印到控制台并在上面的示例中使用的 JSON 字符串与从请求中读取的内容完全相同,那么为什么 JSON 解析会抛出请求数据的错误而不是完全相同的字符串?
更新:
我能找到让它工作的唯一方法是使用下面的代码(这对我来说真的毫无意义)。
try {
// Attempt to call service method.
final parsedJson = await r.readAsString();
final allJson = jsonDecode(parsedJson);
final _AddUserArgs args = _AddUserArgs.fromJson(
jsonDecode(allJson),
);
final AddUserResult result = await exampleService.addUser(
user: args.user,
);
return _rpcResp.Ok(
json: jsonEncode(
result.toJson(),
),
);
}
我认为由于这些是嵌套类,因此出于某种原因需要对它们中的每一个调用 jsonDecode,因此我尝试将此代码添加到生成的反序列化代码中。
_$_AddUserArgs_Freezed _$_$_AddUserArgs_FreezedFromJson(
Map<String, dynamic> json) {
return _$_AddUserArgs_Freezed(
user: json['user'] == null
? null
: User.fromJson(
jsonDecode(json['user']) as Map<String, dynamic>,
),
);
}
但这没有成功。我可以看到第一个 jsonDecode 调用返回动态,这解决了问题。
type 'String' is not a subtype of type 'Map<String, dynamic>'
总的来说,我对这种行为感到非常困惑。为什么我不能简单地将 String 转换为 dynamic 或 Map ?更好的是,我为什么要这样做?jsonDecode 返回动态。此外,当我使用原始字符串时,甚至没有发生这些问题。
更新 2;
现在更加困惑的是,我试图至少将似乎需要的 2 个 json 调用抽象为一个名为 decode 的函数,如下所示。
dynamic decode(dynamic json) {
final newJson = jsonDecode(json);
return jsonDecode(newJson);
}
现在我得到这个错误
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
我 100% 确定我在这里做错了什么,或者只是不明白。我不确定那是什么。