0

我正在尝试使用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% 确定我在这里做错了什么,或者只是不明白。我不确定那是什么。

4

1 回答 1

0

这个问题最终成为我的代码中的一个错误,不确定它有多常见,但以防万一其他人遇到它 - 发生了不止一次对 jsonEncode 函数的调用,这导致 json 格式不正确。

于 2020-05-13T08:10:01.677 回答