DEV Community

Kenji Tomita
Kenji Tomita

Posted on

Safe Handling of Enums in Flutter Apps with OpenAPI Generator

Overview

In the development of iOS and Android apps using Flutter, the use of type-safe data structures is key to enhancing the robustness of applications. Enums are very suitable for representing a set of fixed values, but careful handling is required when integrating with API responses. In this article, I will explain how to use enums in Flutter and their caveats, and introduce how these issues can be resolved by using the enumUnknownDefaultCase=true option.

Background

  • OpenAPI Version: 3.0.0
  • Generator Used: dart-dio

The Convenience and Pitfalls of Enums

Enums are extremely convenient in Flutter for managing states or handling selection options concisely. However, when enum values are closely tied to backend APIs, unexpected API responses can cause problems with enum usage.

Inconsistency Between Enums and APIs

When API responses contain enum values, those values must match the Flutter app's enum definitions exactly. However, if the API unexpectedly returns new values, the frontend code will by default either throw an error or risk ignoring the new values.

Problems with Dynamic Data Sets

When enum values are added on the server side, existing client apps cannot recognize new values until they are updated. This issue is especially serious in environments where the API evolves without frequent application updates.

What is enumUnknownDefaultCase=true?

The OpenAPI generator has an option called enumUnknownDefaultCase. When set to true, it allows handling unknown enum values as a default case.

Issues Resolved by This Option

  • Backward Compatibility: Even if new enum values are added, existing applications continue to operate without crashing.
  • Improved Maintainability: Changes in the API do not require frequent updates to the client.

Sample Code

When using the OpenAPI Generator, the yaml file definition looks like this:

components:
  schemas:
    Response:
      type: object
      required:
        - status
      properties:
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
Enter fullscreen mode Exit fullscreen mode

This definition, when used to generate Dart code, behaves in such a way that it throws an exception if it receives any enum values other than the specified ACTIVE or INACTIVE.

const ResponseStatusEnum _$responseStatusEnum_ACTIVE =
    const ResponseStatusEnum._('ACTIVE');
const ResponseStatusEnum _$responseStatusEnum_INACTIVE =
    const ResponseStatusEnum._('INACTIVE');

ResponseStatusEnum _$responseStatusEnumValueOf(String name) {
  switch (name) {
    case 'ACTIVE':
      return _$responseStatusEnum_ACTIVE;
    case 'INACTIVE':
      return _$responseStatusEnum_INACTIVE;
    default:
      throw new ArgumentError(name);
  }
}
Enter fullscreen mode Exit fullscreen mode

However, setting the enumUnknownDefaultCase=true option includes a new item called unknownDefaultOpenApi in the generated code, which allows for the safe handling of unknown values in case of enum mismatches.

const ResponseStatusEnum _$responseStatusEnum_ACTIVE =
    const ResponseStatusEnum._('ACTIVE');
const ResponseStatusEnum _$responseStatusEnum_INACTIVE =
    const ResponseStatusEnum._('INACTIVE');
const ResponseStatusEnum _$responseStatusEnum_unknownDefaultOpenApi =
    const ResponseStatusEnum._('unknownDefaultOpenApi');

ResponseStatusEnum _$responseStatusEnumValueOf(String name) {
  switch (name) {
    case 'ACTIVE':
      return _$responseStatusEnum_ACTIVE;
    case 'INACTIVE':
      return _$responseStatusEnum_INACTIVE;
    case 'unknownDefaultOpenApi':
      return _$responseStatusEnum_unknownDefaultOpenApi;
    default:
      return _$responseStatusEnum_unknownDefaultOpenApi;
  }
}
Enter fullscreen mode Exit fullscreen mode

With this behavior change, even if the API adds new enum values, the client application can handle those values as unknownDefaultOpenApi without needing an update. This enhances the flexibility of the app and reduces the maintenance effort.

Conclusion

The use of enums is a very powerful tool in Flutter app development, but it is important to consider the integration with the backend. By utilizing the enumUnknownDefaultCase=true option, we can flexibly respond to unexpected changes in the API.

Top comments (0)