google / protobuf.dart

Runtime library for Dart protobufs
https://pub.dev/packages/protobuf
BSD 3-Clause "New" or "Revised" License
527 stars 183 forks source link

Repeated enum does not honor ignoreUnknownFields #849

Open Anushi1998 opened 1 year ago

Anushi1998 commented 1 year ago

Consider following snippet of code:

import 'dart:convert';

import 'response.pb.dart';

void main() {
  final response = Response()
    ..repeatedEnumList.addAll([EnumType.ENUM_TYPE_C, EnumType.ENUM_TYPE_B])
    ..singleEnumValue = EnumType.ENUM_TYPE_A;

  final json = response.toProto3Json() as Map<String, dynamic>;
  print(json);
  final serverAndClientInSync = Response.create()..mergeFromProto3Json(json);

  // WORKS
  final json2 = json;
  json2['singleEnumValue'] = 'ENUM_TYPE_CLIENT_UNAWARE';
  print(json2);
  final worksForUpgradedSingleField = Response.create()
    ..mergeFromProto3Json(json2, ignoreUnknownFields: true);

  // FAILS
  final json3 = json;
  json3['repeatedEnumList'][0] = 'ENUM_TYPE_CLIENT_UNAWARE';
  print(json3);
  final failsForUpgradedRepeatedEnumField = Response.create()
    ..mergeFromProto3Json(json3, ignoreUnknownFields: true);
}

Output

{repeatedEnumList: [ENUM_TYPE_C, ENUM_TYPE_B], singleEnumValue: ENUM_TYPE_A}
{repeatedEnumList: [ENUM_TYPE_C, ENUM_TYPE_B], singleEnumValue: ENUM_TYPE_CLIENT_UNAWARE}
{repeatedEnumList: [ENUM_TYPE_CLIENT_UNAWARE, ENUM_TYPE_B], singleEnumValue: ENUM_TYPE_CLIENT_UNAWARE}
Unhandled exception:
type 'Null' is not a subtype of type 'EnumType' of 'element'
#0      PbList.add (package:protobuf/src/protobuf/pb_list.dart)
#1      _mergeFromProto3Json.recursionHelper.<anonymous closure> (package:protobuf/src/protobuf/proto3_json.dart:385:24)
#2      _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:625:13)
#3      _mergeFromProto3Json.recursionHelper (package:protobuf/src/protobuf/proto3_json.dart:338:14)
#4      _mergeFromProto3Json (package:protobuf/src/protobuf/proto3_json.dart:416:3)
#5      GeneratedMessage.mergeFromProto3Json (package:protobuf/src/protobuf/generated_message.dart:267:7)
#6      main (package:enums/enums.dart:26:7)
#7      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:296:19)
#8      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:189:12)

Full Code Snippet: https://github.com/Anushi1998/DartProtobufBug/

In case of single enum field, unknown value is ignored but for repeated enums it tried to add null. If we can avoid adding null here it will support backward compatability for repeated enums too. Happy to send a patch if this approach works.

osa1 commented 1 year ago

Good catch. I think your fix should work, convertProto3JsonValue returns null only on unknown enum values, so just skipping those when adding to the list should work.