Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] [dart-dio] Generated deserialize() for Map<String, anything> targetType throws exception for json_serializable #19495

Closed
4 of 6 tasks
rankoz opened this issue Aug 30, 2024 · 0 comments · Fixed by #19496

Comments

@rankoz
Copy link
Contributor

rankoz commented Aug 30, 2024

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Deserializing fails for any type of dictionary return type for 'json_serializable'. Even as simple Map<String, String>.

I/flutter ( 7275): Exception: Cannot deserialize

The problem is here.

openapi-generator version

7.8.0

OpenAPI declaration file content or url
openapi: 3.1.0
info:
  title: Example API
  version: 1.0.0
paths:
  /example:
    get:
      summary: Returns a map of strings
      responses:
        '200':
          description: A map of key-value pairs
          content:
            application/json:
              schema:
                type: object
                additionalProperties:
                  type: string
Generation Details
Steps to reproduce
Related issues/PRs
Suggest a fix

In deserialize.mustache, the regular expression for Map type looks looks like this:

final _regMap = RegExp(r'^Map<String,(.*)>$');

... it will pick up everything after a comma.

Generated code for the above spec will have this snippet:

    Map<String, String>? _responseData;

    try {
final rawData = _response.data;
_responseData = rawData == null ? null : deserialize<Map<String, String>, String>(rawData, 'Map<String, String>', growable: true);
    } catch (error, stackTrace) {

The second parameter passed to deserialize (targetType), "Map<String, String>", contains space after a comma.

if (value is Map && (match = _regMap.firstMatch(targetType)) != null) {
  // targetType resolves to ' String' with a space in front and recursive call below will not find matching type
  targetType = match![1]!; // ignore: parameter_assignments.
  return Map<dynamic, BaseType>.fromIterables(
    value.keys,
    value.values.map((dynamic v) => deserialize<BaseType, BaseType>(v, targetType, growable: growable)),
  ) as ReturnType;
}

Fixing the above by adding .trim() causes a second issue:
Error: type '_Map<dynamic, String>' is not a subtype of type 'Map<String, String>' in type cast

Therefore the correct code for the above snippet, considering that _regMap is looking for Map<String, ...> should be:

if (value is Map && (match = _regMap.firstMatch(targetType)) != null) {
  targetType = match![1]!.trim(); // ignore: parameter_assignments
  return Map<String, BaseType>.fromIterables(
    value.keys as Iterable<String>,
    value.values.map((dynamic v) => deserialize<BaseType, BaseType>(v, targetType, growable: growable)),
  ) as ReturnType;
}

I will do a PR for this in a minute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant