1

Posting this question to answer it myself. Hope this helps someone.

The problem: Generating code with flutter freezed but changing the to and from json field names to a specific renaming pattern.

Mu'aaz Joosuf
  • 103
  • 1
  • 9

3 Answers3

3

The solution:

build.yaml

Lets say you have a class written in freezed like this

import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:convert';

part 'my_calss.freezed.dart';
part 'my_calss.g.dart';

@freezed
abstract class MyCalss with _$MyCalss {
    const factory MyCalss({
        @required int field1,
        @required String field2,
    }) = _MyCalss;

    factory MyCalss.fromJson(Map<String, dynamic> json) => _$MyCalssFromJson(json);
}


to change the classes my_calss.g.dart to use for example pascal case:

place the following into your build.yaml

# targets:
#   $default:
#     builders:
#       freezed:
#         options:
#           union_key: type
#           union_value_case: pascal

targets:
  $default:
    builders:
      json_serializable:
        options:
          # Options configure how source code is generated for every
          # `@JsonSerializable`-annotated class in the package.
          #
          # The default value for each is listed.
          any_map: false
          checked: false
          constructor: ""
          create_factory: true
          create_field_map: false
          create_to_json: true
          disallow_unrecognized_keys: false
          explicit_to_json: false
          field_rename: pascal
          generic_argument_factories: false
          ignore_unannotated: false
          include_if_null: true

The main field of interest is field_rename which can be any value from the enum FieldRename in json_serializable listed below


/// Values for the automatic field renaming behavior for [JsonSerializable].
enum FieldRename {
  /// Use the field name without changes.
  none,

  /// Encodes a field named `kebabCase` with a JSON key `kebab-case`.
  kebab,

  /// Encodes a field named `snakeCase` with a JSON key `snake_case`.
  snake,

  /// Encodes a field named `pascalCase` with a JSON key `PascalCase`.
  pascal,

  /// Encodes a field named `screamingSnakeCase` with a JSON key
  /// `SCREAMING_SNAKE_CASE`
  screamingSnake,
}

Originally, i found this github page here which said to do the following

However, when I write this, there is an error (when I checked the generated file, it was generated twice)
@freezed
@JsonSerializable(fieldRename: FieldRename.snake)
class Example with _$Example {
  factory Example() = GeneratedClass;
}
So rewriting it this way works fine.
@freezed
class Example with _$Example {
  @JsonSerializable(fieldRename: FieldRename.snake)
  factory Example() = GeneratedClass;
}

Neither of these solutions helped me, only editing the build.yaml file fixed the issue.

Versions I am using

  #Freezed 
  freezed_annotation: ^2.1.0
 #json annotations
  json_annotation: ^4.6.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: ^2.2.0
  flutter_lints: ^2.0.1
  freezed: ^2.1.0+1
  json_serializable: ^6.3.1

Mu'aaz Joosuf
  • 103
  • 1
  • 9
3

Actually, I found an easier way. It may be new, but it is somewhat documented as well, how to mix freezed with JsonSerializable notation.

https://pub.dev/packages/freezed (Look for ”What about @JsonSerializable annotation?” section)

This kind of code worked for me like a charm.

@freezed
class Account with _$Account {
  // ignore: invalid_annotation_target
  @JsonSerializable(fieldRename: FieldRename.snake)
  const factory Account(
      {required int? id,
      required int? userId, // snake case to camel case conversion works
      required String? name,
      required int? balance}) = _Account;

  factory Account.fromJson(Map<String, dynamic> json) =>
      _$AccountFromJson(json);
}
barley
  • 4,403
  • 25
  • 28
0

you can also use @JsonKey(name: 'field_rename') for specifying json key

@freezed
abstract class MyCalss with _$MyCalss {
    const factory MyCalss({
        @JsonKey(name: 'field_name') @required int fieldName,
        @JsonKey(name: 'field_age') @required String fieldAge,
        @required String gender,
    }) = _MyCalss;

    factory MyCalss.fromJson(Map<String, dynamic> json) => _$MyCalssFromJson(json);
}