json_fields 0.1.0 copy "json_fields: ^0.1.0" to clipboard
json_fields: ^0.1.0 copied to clipboard

Generates type-safe, compile-time-checked JSON field path accessors for classes annotated with @JsonSerializable. Ideal for Firebase partial updates.

example/example.md

Define your models #

import 'package:json_annotation/json_annotation.dart';

part 'example.g.dart';

@JsonSerializable(fieldRename: FieldRename.snake)
class User {
  final String firstName;
  final String lastName;
  final int age;
  final Address address;
  final String email;
  final String? sessionToken;

  User({
    required this.firstName,
    required this.lastName,
    required this.age,
    required this.address,
    required this.email,
    this.sessionToken,
  });

  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);

  Map<String, dynamic> toJson() => _$UserToJson(this);

  // <-- enables User.fields
  static const fields = $UserFields();
}

@JsonSerializable(fieldRename: FieldRename.snake)
class Address {
  final String street;
  final String city;
  final String zipCode;

  Address({required this.street, required this.city, required this.zipCode});

  factory Address.fromJson(Map<String, dynamic> json) =>
      _$AddressFromJson(json);

  Map<String, dynamic> toJson() => _$AddressToJson(this);

  // <-- enables Address.fields
  static const fields = $AddressFields();
}

Use it #

Basic field paths #

User.fields.firstName;      // 'first_name'
User.fields.lastName;       // 'last_name'
User.fields.age;            // 'age'
User.fields.email;          // 'email'
User.fields.sessionToken;   // 'session_token'

Nested paths #

User.fields.address;             // 'address'
User.fields.address.street;      // 'address.street'
User.fields.address.city;        // 'address.city'
User.fields.address.zipCode;     // 'address.zip_code'

The generated extension types implement String, so the values are usable anywhere a String is expected.

Firebase-style partial updates #

await firestore.collection('users').doc(uid).update({
  User.fields.firstName: 'Jane',
  User.fields.address.city: 'NYC',
  User.fields.address.zipCode: '10001',
});

If you ever rename firstName to givenName, this call breaks at compile time, exactly what hardcoded strings can never do for you.

Firestore queries #

firestore
    .collection('users')
    .where(User.fields.address.city, isEqualTo: 'NYC')
    .orderBy(User.fields.lastName);

Custom path separators #

The default . separator works for Firestore-style document paths. To generate paths joined with / (e.g. for Firebase Realtime Database) or any other separator, set the builder option in your project's build.yaml:

targets:
  $default:
    builders:
      json_fields|json_fields:
        options:
          separator: '/'

After re-running build_runner, the generated paths use the new separator:

User.fields.address.street;   // 'address/street'    (was 'address.street')
User.fields.address.city;     // 'address/city'

Individual field names are still controlled by FieldRename and @JsonKey(name:); only the join character between nested segments changes.

Custom path prefixes #

When your data lives under a non-class root (e.g. users/$uid/...), pass a prefix to the accessor's public constructor:

const userFields = $UserFields(prefix: 'users/abc123');

userFields.firstName;            // 'users/abc123.first_name'
userFields.address.city;         // 'users/abc123.address.city'

The prefix flows through nested accessors automatically.

Renaming a field is a compile error #

// After renaming `firstName` to `givenName` on User:
User.fields.firstName;
//          ^^^^^^^^^
// Compile error: getter 'firstName' isn't defined for the type '$UserFields'.

Existing call sites that referenced the old name fail to compile until they're updated, which is exactly what hardcoded string keys can't do for you.

Output, when printed #

Printing each accessor and a sample Firebase-style update map produces:

first_name
last_name
age
email
session_token
address
address.street
address.city
address.zip_code
{first_name: Jane, address.city: NYC, address.zip_code: 10001}
users/abc123.first_name
users/abc123.address.city
0
likes
160
points
97
downloads

Documentation

API reference

Publisher

verified publisherbirju.dev

Weekly Downloads

Generates type-safe, compile-time-checked JSON field path accessors for classes annotated with @JsonSerializable. Ideal for Firebase partial updates.

Repository (GitHub)
View/report issues

Topics

#json #codegen #build-runner #firebase #json-serializable

License

BSD-3-Clause (license)

Dependencies

analyzer, build, code_builder, json_annotation, source_gen, source_helper

More

Packages that depend on json_fields