diff --git a/temporalio/lib/temporalio/converters/payload_converter/json_protobuf.rb b/temporalio/lib/temporalio/converters/payload_converter/json_protobuf.rb index 897b7c79..db12dce7 100644 --- a/temporalio/lib/temporalio/converters/payload_converter/json_protobuf.rb +++ b/temporalio/lib/temporalio/converters/payload_converter/json_protobuf.rb @@ -22,7 +22,7 @@ def to_payload(value, hint: nil) # rubocop:disable Lint/UnusedMethodArgument Api::Common::V1::Payload.new( metadata: { 'encoding' => ENCODING, 'messageType' => value.class.descriptor.name }, - data: value.to_json + data: value.to_json.b ) end diff --git a/temporalio/test/converters/payload_converter_test.rb b/temporalio/test/converters/payload_converter_test.rb index b28baf60..ac0431a2 100644 --- a/temporalio/test/converters/payload_converter_test.rb +++ b/temporalio/test/converters/payload_converter_test.rb @@ -72,6 +72,17 @@ def test_default_converter # outside of Ruby) require 'json/add/time' assert_payload time, 'json/plain', time.to_json + + # Proto payloads with multi-byte UTF-8 characters (em-dash U+2014) are serialized correctly + proto_with_multibyte = Temporalio::Api::Common::V1::WorkflowExecution.new(workflow_id: 'test — emdash') + payload = assert_payload( + proto_with_multibyte, + 'json/protobuf', + # The .b method converts UTF-8 to ASCII-8BIT/binary encoding, which is required by the Payload data field. + # The multi-byte em-dash character (U+2014) becomes the byte sequence \xE2\x80\x94 in UTF-8. + "{\"workflowId\":\"test \xE2\x80\x94 emdash\"}".b + ) + assert_equal 'temporal.api.common.v1.WorkflowExecution', payload.metadata['messageType'] end def test_binary_proto