simolus3 / drift

Drift is an easy to use, reactive, typesafe persistence library for Dart & Flutter.
https://drift.simonbinder.eu/
MIT License
2.64k stars 370 forks source link

Views and Tables use different Json key capitalization conventions #2646

Open Adam-Langley opened 1 year ago

Adam-Langley commented 1 year ago

I am using the toJson/fromJson methods of data classes generated by Drift to essentially 'map' between data records which have the same schema.

In doing so, I am getting runtime errors, because it appears that dart entity classes generated for 'TableInfo' is using different json conventions to entity classes generated for 'ViewInfo'.

The View is even just a view on the same Table...

This is preventing me from doing this...

ServerHazard source = ServerHazard(); // imagine this is filled with data
HazardsViewData destination = HazardsViewData.fromJson(source.toJson());

Example snippet from a view:

factory HazardsViewData.fromJson(Map<String, dynamic> json,
      {ValueSerializer? serializer}) {
    serializer ??= driftRuntimeOptions.defaultSerializer;
    return HazardsViewData(
      clonedFromEntityId:
          serializer.fromJson<Guid?>(json['cloned_from_entity_id']),
      machineId: serializer.fromJson<Guid>(json['machine_id']),
      referenceCode: serializer.fromJson<String?>(json['reference_code']),

Example snippet from the same entity as a Table:

factory ServerHazard.fromJson(Map<String, dynamic> json,
      {ValueSerializer? serializer}) {
    serializer ??= driftRuntimeOptions.defaultSerializer;
    return ServerHazard(
      clonedFromEntityId:
          serializer.fromJson<Guid?>(json['clonedFromEntityId']),
      machineId: serializer.fromJson<Guid>(json['machineId']),
      referenceCode: serializer.fromJson<String?>(json['referenceCode']),
Adam-Langley commented 1 year ago

I've managed to move ahead - I've found the option use_column_name_as_json_key_when_defined_in_moor_file (set to false) to force all json keys to be cased the same as in dart (pascal), instead of from the tables (snake).

Here's my build file for anyone else with this issue:

targets:
  $default:
    builders:

      drift_dev:
        options:
          use_column_name_as_json_key_when_defined_in_moor_file: false

I'll leave the bug here, however, as I think the default behavior should be consistent so this doesnt bite people...

simolus3 commented 1 year ago

Yeah, maybe that should be the default in the next breaking version. I think the option has essentially been introduced to preserve backwards compatibility, but then I forgot about and so the divergence is still there.

CharlotteJu commented 8 months ago

Hello @simolus3, Allow me to add a comment to this topic. I tried to set this option to true and false. I also chose the PascalCase option for my variables. But yet my toJson() always generates a value in snakeCase... Is there a way to correct this?

targets:
  $default:
    builders:
      drift_dev:
        options:
          case_from_dart_to_sql: PascalCase
          use_column_name_as_json_key_when_defined_in_moor_file: false
class Settings extends Table {
 IntColumn get id => integer()();
  BoolColumn get ctEnabled =>
      boolean().withDefault(const Constant(false)).named("CTEnabled")();
  TextColumn get userName => text().withLength(max: 32).nullable()();

  @override
  Set<Column> get primaryKey => {id};
  }

In generated file :

@override
  Map<String, dynamic> toJson({ValueSerializer? serializer}) {
    serializer ??= driftRuntimeOptions.defaultSerializer;
    return <String, dynamic>{
      'id': serializer.toJson<int>(id),
      'ctEnabled': serializer.toJson<bool>(ctEnabled),
      'userName': serializer.toJson<String?>(userName),
    };
  }