From dc96331c49985f264c7d129ca3d5604889eddd79 Mon Sep 17 00:00:00 2001 From: James Watkins-Harvey Date: Fri, 22 May 2026 17:40:00 -0400 Subject: [PATCH] fix: handle bytes in map and repeated fields in toProto3JSON --- .../test-fixtures/proto/test.json | 10 +++++++++ .../test-fixtures/proto/test.proto | 2 ++ .../typescript/src/toproto3json.ts | 7 +++---- .../typescript/test/unit/map.ts | 10 +++++++++ .../typescript/test/unit/repeated.ts | 21 +++++++++++++++++++ 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.json b/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.json index e107366b32af..5f9a37c68f3f 100644 --- a/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.json +++ b/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.json @@ -91,6 +91,11 @@ "keyType": "string", "type": "Enum", "id": 6 + }, + "bytesMapField": { + "keyType": "string", + "type": "bytes", + "id": 7 } } }, @@ -128,6 +133,11 @@ "rule": "repeated", "type": "Enum", "id": 7 + }, + "repeatedBytes": { + "rule": "repeated", + "type": "bytes", + "id": 8 } } }, diff --git a/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.proto b/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.proto index a2cf06ff9cc8..0884d119f592 100644 --- a/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.proto +++ b/core/packages/proto3-json-serializer-nodejs/test-fixtures/proto/test.proto @@ -56,6 +56,7 @@ message MessageWithMap { map string_map_field = 4; map long_map_field = 5; map enum_map_field = 6; + map bytes_map_field = 7; } message MapValue { @@ -68,6 +69,7 @@ message MessageWithRepeated { repeated string one_more_repeated_string = 5; repeated int64 repeated_long = 6; repeated Enum repeated_enum = 7; + repeated bytes repeated_bytes = 8; } message RepeatedValue { diff --git a/core/packages/proto3-json-serializer-nodejs/typescript/src/toproto3json.ts b/core/packages/proto3-json-serializer-nodejs/typescript/src/toproto3json.ts index 3a441193fa6f..affeee3dad6d 100644 --- a/core/packages/proto3-json-serializer-nodejs/typescript/src/toproto3json.ts +++ b/core/packages/proto3-json-serializer-nodejs/typescript/src/toproto3json.ts @@ -47,6 +47,9 @@ function convertSingleValue(value: JSONValue | object): JSONValue { if (value?.constructor?.name === 'Long') { return (value as LongStub).toString(); } + if (Buffer.isBuffer(value) || value instanceof Uint8Array) { + return bytesToProto3JSON(value); + } throw new Error(`toProto3JSON: don't know how to convert value ${value}`); } return value; @@ -200,10 +203,6 @@ export function toProto3JSON( result[key] = value; continue; } - if (Buffer.isBuffer(value) || value instanceof Uint8Array) { - result[key] = bytesToProto3JSON(value); - continue; - } result[key] = convertSingleValue(value); continue; } diff --git a/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/map.ts b/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/map.ts index 05aa1ef60b6c..718c0622f2ea 100644 --- a/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/map.ts +++ b/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/map.ts @@ -40,6 +40,10 @@ function testMap(root: protobuf.Root) { 'minus one': '-1', zero: '0', }, + bytesMapField: { + key1: 'dmFsdWUgMQo=', + key2: 'dmFsdWUgMgo=', + }, }); const json = { mapField: { @@ -61,6 +65,10 @@ function testMap(root: protobuf.Root) { zero: '0', }, enumMapField: {}, + bytesMapField: { + key1: 'dmFsdWUgMQo=', + key2: 'dmFsdWUgMgo=', + }, }; it('serializes to proto3 JSON', () => { @@ -90,6 +98,7 @@ function testEnumMap(root: protobuf.Root) { key1: 'UNKNOWN', key2: 'KNOWN', }, + bytesMapField: {}, }; const jsonWithNumericEnums = { mapField: {}, @@ -99,6 +108,7 @@ function testEnumMap(root: protobuf.Root) { key1: 0, key2: 1, }, + bytesMapField: {}, }; it('serializes to proto3 JSON with string enums', () => { diff --git a/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/repeated.ts b/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/repeated.ts index 2df7cac67334..00d59b72dc92 100644 --- a/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/repeated.ts +++ b/core/packages/proto3-json-serializer-nodejs/typescript/test/unit/repeated.ts @@ -160,6 +160,27 @@ function testRepeatedEnum(root: protobuf.Root) { }); } +function testRepeatedBytes(root: protobuf.Root) { + const MessageWithRepeated = root.lookupType('test.MessageWithRepeated'); + const message = MessageWithRepeated.fromObject({ + repeatedBytes: ['dmFsdWUgMQo=', 'dmFsdWUgMgo='], + }); + const json = { + repeatedBytes: ['dmFsdWUgMQo=', 'dmFsdWUgMgo='], + }; + + it('serializes to proto3 JSON', () => { + const serialized = toProto3JSON(message); + assert.deepStrictEqual(serialized, json); + }); + + it('deserializes from proto3 JSON', () => { + const deserialized = fromProto3JSON(MessageWithRepeated, json); + assert.deepStrictEqual(deserialized, message); + }); +} + testTwoTypesOfLoad('repeated fields', testRepeated); testTwoTypesOfLoad('empty repeated fields', testEmptyRepeated); testTwoTypesOfLoad('repeated enums', testRepeatedEnum); +testTwoTypesOfLoad('repeated bytes', testRepeatedBytes);