@@ -797,7 +797,7 @@ func (annotate *annotateModel) annotateField(field *api.Field) {
797797 FieldBehaviorRequired : fieldRequired ,
798798 DefaultValue : defaultValue ,
799799 FromJson : annotate .createFromJsonLine (field , state , implicitPresence ),
800- ToJson : createToJsonLine (field , state , implicitPresence ),
800+ ToJson : createToJsonLine (field , state ),
801801 ConstDefault : constDefault ,
802802 }
803803}
@@ -853,8 +853,85 @@ func (annotate *annotateModel) keyDecoder(typez api.Typez) string {
853853 api .SINT64_TYPE ,
854854 api .SFIXED64_TYPE :
855855 return "decodeIntKey"
856+ case api .UINT64_TYPE ,
857+ api .FIXED64_TYPE :
858+ return "decodeUint64Key"
859+ case api .BOOL_TYPE :
860+ return "decodeBoolKey"
861+ default :
862+ panic (fmt .Sprintf ("unsupported key type: %d" , typez ))
863+ }
864+ }
865+
866+ // encoder returns a string that encodes the given field name and a bool that indicates whether the
867+ // field requires encoding.
868+ //
869+ // For example:
870+ //
871+ // encoder(api.STRING_TYPE, "a_string_field") => ("a_string_field", false)
872+ // encoder(api.MESSAGE_TYPE, "a_message_field") => ("a_message_field.toJson()", true)
873+ func encoder (typez api.Typez , name string ) (string , bool ) {
874+ switch typez {
875+ case api .INT64_TYPE ,
876+ api .SINT64_TYPE ,
877+ api .SFIXED64_TYPE ,
878+ api .FIXED64_TYPE ,
879+ api .UINT64_TYPE :
880+ // All 64-bit integer types are encoded as strings. In Dart, these may be
881+ // represented as `int` or `BigInt`.
882+ return fmt .Sprintf ("%s.toString()" , name ), true
883+ case api .FLOAT_TYPE ,
884+ api .DOUBLE_TYPE :
885+ // A special encoder is needed to handle NaN and Infinity.
886+ return fmt .Sprintf ("encodeDouble(%s)" , name ), true
887+ case api .INT32_TYPE ,
888+ api .FIXED32_TYPE ,
889+ api .SFIXED32_TYPE ,
890+ api .SINT32_TYPE ,
891+ api .UINT32_TYPE :
892+ // All 32-bit integer types are encoded as JSON numbers.
893+ return name , false
894+ case api .BOOL_TYPE :
895+ return name , false
896+ case api .STRING_TYPE :
897+ return name , false
898+ case api .BYTES_TYPE :
899+ return fmt .Sprintf ("encodeBytes(%s)" , name ), true
900+ case api .MESSAGE_TYPE , api .ENUM_TYPE :
901+ return fmt .Sprintf ("%s.toJson()" , name ), true
902+ default :
903+ panic (fmt .Sprintf ("unsupported type: %d" , typez ))
904+ }
905+ }
906+
907+ // keyEncoder returns a string that encodes the given field name and a bool that indicates whether the
908+ // field requires encoding
909+ //
910+ // For example:
911+ //
912+ // keyEncoder(api.STRING_TYPE, "e.key") => ("e.key", false)
913+ // keyEncoder(api.INT32_TYPE, "e.key") => ("e.key.toString()", true)
914+ func keyEncoder (typez api.Typez , name string ) (string , bool ) {
915+ // JSON objects can only contain string keys so non-String types need to be encoded as strings.
916+ // Supported key types are defined here:
917+ // https://protobuf.dev/programming-guides/proto3/#maps
918+ switch typez {
919+ case api .STRING_TYPE :
920+ return name , false
921+ case api .INT32_TYPE ,
922+ api .FIXED32_TYPE ,
923+ api .SFIXED32_TYPE ,
924+ api .SINT32_TYPE ,
925+ api .UINT32_TYPE ,
926+ api .INT64_TYPE ,
927+ api .SINT64_TYPE ,
928+ api .SFIXED64_TYPE ,
929+ api .UINT64_TYPE ,
930+ api .FIXED64_TYPE :
931+ return fmt .Sprintf ("%s.toString()" , name ), true
932+ case api .BOOL_TYPE :
933+ return fmt .Sprintf ("%s.toString()" , name ), true
856934 default :
857- // TODO(https://github.com/googleapis/google-cloud-dart/issues/95): Support all key types.
858935 panic (fmt .Sprintf ("unsupported key type: %d" , typez ))
859936 }
860937}
@@ -904,57 +981,34 @@ func (annotate *annotateModel) createFromJsonLine(field *api.Field, state *api.A
904981 return fmt .Sprintf ("switch (%s) { null => %s, Object $1 => %s($1)}" , data , defaultValue , decoder )
905982}
906983
907- func createToJsonLine (field * api.Field , state * api.APIState , required bool ) string {
984+ func createToJsonLine (field * api.Field , state * api.APIState ) string {
908985 name := fieldName (field )
909- message := state .MessageByID [field .TypezID ]
910-
911- isList := field .Repeated
912- isMap := message != nil && message .IsMap
913-
914- bang := "!"
915- if required {
916- bang = ""
917- }
918986
919987 switch {
920- case isList :
921- switch field .Typez {
922- case api .BYTES_TYPE :
923- return fmt .Sprintf ("encodeListBytes(%s)" , name )
924- case api .MESSAGE_TYPE , api .ENUM_TYPE :
925- return fmt .Sprintf ("encodeList(%s)" , name )
926- default :
927- // identity
928- return name
988+ case field .Repeated :
989+ if encoder , encodingRequired := encoder (field .Typez , "i" ); encodingRequired {
990+ return fmt .Sprintf (
991+ "[for (final i in %s) %s]" ,
992+ name , encoder )
929993 }
930- case isMap :
931- valueField := message .Fields [1 ]
994+ return name
995+ case field .Map :
996+ message := state .MessageByID [field .TypezID ]
997+ keyType := message .Fields [0 ].Typez
998+ keyEncoder , keyEncodingRequired := keyEncoder (keyType , "e.key" )
999+ valueType := message .Fields [1 ].Typez
1000+ valueEncoder , valueEncodingRequired := encoder (valueType , "e.value" )
9321001
933- switch valueField .Typez {
934- case api .BYTES_TYPE :
935- return fmt .Sprintf ("encodeMapBytes(%s)" , name )
936- case api .MESSAGE_TYPE , api .ENUM_TYPE :
937- return fmt .Sprintf ("encodeMap(%s)" , name )
938- default :
939- // identity
940- return name
1002+ if keyEncodingRequired || valueEncodingRequired {
1003+ return fmt .Sprintf (
1004+ "{for (final e in %s.entries) %s: %s}" ,
1005+ name , keyEncoder , valueEncoder )
9411006 }
942- case field .Typez == api .MESSAGE_TYPE || field .Typez == api .ENUM_TYPE :
943- return fmt .Sprintf ("%s%s.toJson()" , name , bang )
944- case field .Typez == api .BYTES_TYPE :
945- return fmt .Sprintf ("encodeBytes(%s)" , name )
946- case field .Typez == api .INT64_TYPE || field .Typez == api .SINT64_TYPE ||
947- field .Typez == api .SFIXED64_TYPE :
948- return fmt .Sprintf ("encodeInt64(%s)" , name )
949- case field .Typez == api .FIXED64_TYPE || field .Typez == api .UINT64_TYPE :
950- return fmt .Sprintf ("encodeUint64(%s)" , name )
951- case field .Typez == api .FLOAT_TYPE || field .Typez == api .DOUBLE_TYPE :
952- return fmt .Sprintf ("encodeDouble(%s)" , name )
953- default :
1007+ return name
9541008 }
9551009
956- // No encoding necessary.
957- return name
1010+ enc , _ := encoder ( field . Typez , name )
1011+ return enc
9581012}
9591013
9601014// buildQueryLines builds a string or strings representing query parameters for the given field.
0 commit comments