google / json_serializable.dart

Generates utilities to aid in serializing to/from JSON.
https://pub.dev/packages/json_serializable
BSD 3-Clause "New" or "Revised" License
1.56k stars 399 forks source link

how to convert the enum to the value declared by @JsonValue? #653

Closed LichKing-2234 closed 4 years ago

LichKing-2234 commented 4 years ago

how can I convert the enum to the value declared by @JsonValue, I don‘t want to create a class to wrap the enum. Pls, help me, thanks!

kevmoo commented 4 years ago

Enums work fine. What's the specific problem?

https://github.com/dart-lang/json_serializable/blob/4aaf8e01bbd5f15e0f201fcb98420b109dfe134a/json_serializable/test/integration/json_test_common.dart#L10-L19

https://github.com/dart-lang/json_serializable/blob/4aaf8e01bbd5f15e0f201fcb98420b109dfe134a/json_serializable/test/integration/json_test_example.g.dart#L82-L90

LichKing-2234 commented 4 years ago
import 'package:json_annotation/json_annotation.dart';

part 'types.g.dart';

enum ABC {
  @JsonValue(0)
  HAHA,
  @JsonValue(1)
  HEHE,
  @JsonValue(2)
  XIXI
}

I create a dart file named types, then run flutter pub run build_runner build. the types.g.dart not create automatic.

kevmoo commented 4 years ago

Oh! You won't get a file generated here. Only for classes annotated @JsonSerializable

On Wed, Jun 10, 2020 at 8:04 PM Arthas notifications@github.com wrote:

import 'package:json_annotation/json_annotation.dart';

part 'types.g.dart';

enum ABC { @JsonValue(0) HAHA, @JsonValue(1) HEHE, @JsonValue(2) XIXI }

I create a dart file named types, then run flutter pub run build_runner build. the types.g.dart not create automatic.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dart-lang/json_serializable/issues/653#issuecomment-642377199, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAEFCXDBD3L25SLCGBDFDTRWBCSZANCNFSM4N2OU7HA .

AhmedNourJamalElDin commented 4 years ago

I needed this feature badly, I have inheritance and multiple different types.

so I need to deserialize type first, then create an instance based on the type.

For now, I've copied the generated code to my factory class. is there any other way to do this?

kevmoo commented 4 years ago

Could you show a bit more code than just the enum?

Could you share what you hope is generated?

AhmedNourJamalElDin commented 4 years ago

Hi @kevmoo ,

I just have a string and I want to convert it to enum.

I have something like this:

enum Type {
  text,
  image,
  unknown,
}

and I have a String, let's say: "text" or "video" (unknown value in my enum) and I would like to convert the string "text" to Type enum i.e. Type.text.

for now, I've copied these to be globally accessible:

T _$enumDecode<T>(Map<T, dynamic> enumValues,
    dynamic source, {
      T unknownValue,
    }) {
  if (source == null) {
    throw ArgumentError('A value must be provided. Supported values: '
        '${enumValues.values.join(', ')}');
  }

  final value = enumValues.entries
      .singleWhere((e) => e.value == source, orElse: () => null)
      ?.key;

  if (value == null && unknownValue == null) {
    throw ArgumentError('`$source` is not one of the supported values: '
        '${enumValues.values.join(', ')}');
  }
  return value ?? unknownValue;
}

T _$enumDecodeNullable<T>(Map<T, dynamic> enumValues,
    dynamic source, {
      T unknownValue,
    }) {
  if (source == null) {
    return null;
  }
  return _$enumDecode<T>(enumValues, source, unknownValue: unknownValue);
}

const _$TypeEnumMap = {
  Type.text: 'text',
  Type.image: 'image',
  Type.unknown: 'unknown',
};

and I'm using it like this:

final type = _$enumDecodeNullable(_$TypeEnumMap, json['type'], unknownValue: Type.unknown),

I don't think this is too relevant, but it's somehow related: converting a value to enum.

And I have used this Type enum in many different classes and now it's redundant in many generated files i.e. in each file that needs a value of type Type enum.

LichKing-2234 commented 3 years ago

I have forked this repository and support generate the _$EnumMap without as a field of a class. My commit here

You can use @JsonSerializable to enum now, like:

import 'package:json_annotation/json_annotation.dart';

part 'types.g.dart';

@JsonSerializable(
  createFactory: false,
  createToJson: false,
)
enum ABC {
  @JsonValue(0)
  HAHA,
  @JsonValue(1)
  HEHE,
  @JsonValue(2)
  XIXI
}

The best way is to create a new annotation like @JsonEnumSerializable, so I did not create a PR now.

Here is the pubspec usage:

  json_serializable:
    git:
      url: https://github.com/LichKing-2234/json_serializable.dart.git
      ref: v4_x
      path: json_serializable
jhancock4d commented 3 years ago

@LichKing-2234 That is absolutely awesome. Great work! This fixes a major deficiency in Dart.