From 8127b7351cecb7cdb020a39984d4d3e61a081f99 Mon Sep 17 00:00:00 2001 From: Dan Hudlow Date: Sat, 17 May 2025 16:49:05 -0500 Subject: [PATCH 1/2] Add tests for field casing, duplicate field ordering, and unknown field errors when performing JSON deserialization --- packages/protobuf-test/src/json.test.ts | 74 +++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/packages/protobuf-test/src/json.test.ts b/packages/protobuf-test/src/json.test.ts index f6e977410..04fe734ad 100644 --- a/packages/protobuf-test/src/json.test.ts +++ b/packages/protobuf-test/src/json.test.ts @@ -723,6 +723,30 @@ describe("extensions in JSON", () => { }); }); +describe("JsonReadOptions", () => { + describe("ignoreUnknownFields", () => { + test("throws error when false", () => { + expect(() => + fromJsonString(proto3_ts.Proto3MessageSchema, '{ "unknown": 1 }', { + ignoreUnknownFields: false, + }), + ).toThrow(); + }); + test("does not throw error when true", () => { + expect(() => + fromJsonString(proto3_ts.Proto3MessageSchema, '{ "unknown": 1 }', { + ignoreUnknownFields: true, + }), + ).not.toThrow(); + }); + test("defaults to false", () => { + expect(() => + fromJsonString(proto3_ts.Proto3MessageSchema, '{ "unknown": 1 }'), + ).toThrow(); + }); + }); +}); + describe("JsonWriteOptions", () => { describe("alwaysEmitImplicit", () => { test("emits proto3 implicit fields", async () => { @@ -833,6 +857,56 @@ describe("JsonWriteOptions", () => { }); }); +describe("parsing funny JSON", () => { + describe("field casing", () => { + test("is case agnostic", () => { + const a = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singular_string_field": "a" }', + ); + const b = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singularStringField": "b" }', + ); + + expect(a.singularStringField).toBe("a"); + expect(b.singularStringField).toBe("b"); + }); + }); + describe("duplicate fields", () => { + // This depends on the ECMA-262-defined JSON.parse() behavior, which is itself + // specified to choose the last field value for a duplicate field. + test("chooses last field when duplicated", () => { + const a = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singularStringField": "b", "singularStringField": "a" }', + ); + const b = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singularStringField": "a", "singularStringField": "b" }', + ); + + expect(a.singularStringField).toBe("a"); + expect(b.singularStringField).toBe("b"); + }); + // This depends on the ECMA-262-defined behavior for JSON.parse() and + // Object.entries() and the internal preservation of object key order. + test("chooses last field when duplicated, even when fields have different casing", () => { + const a = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singular_string_field": "b", "singularStringField": "a" }', + ); + const b = fromJsonString( + proto3_ts.Proto3MessageSchema, + '{ "singularStringField": "a", "singular_string_field": "b" }', + ); + + expect(a.singularStringField).toBe("a"); + expect(b.singularStringField).toBe("b"); + }); + }); +}); + // Coverage for JSON parse errors to guard against regressions. // We do not cover all cases here. Map fields and oneofs are incomplete, // and bytes, string, and other scalar types are not tested. From 2c109290fb715399b619aaae62c71cfb0cce7747 Mon Sep 17 00:00:00 2001 From: Dan Hudlow Date: Wed, 21 May 2025 01:53:29 -0500 Subject: [PATCH 2/2] Remove field casing test that duplicates protobuf conformance tests --- packages/protobuf-test/src/json.test.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/protobuf-test/src/json.test.ts b/packages/protobuf-test/src/json.test.ts index 04fe734ad..01c41ecb9 100644 --- a/packages/protobuf-test/src/json.test.ts +++ b/packages/protobuf-test/src/json.test.ts @@ -858,21 +858,6 @@ describe("JsonWriteOptions", () => { }); describe("parsing funny JSON", () => { - describe("field casing", () => { - test("is case agnostic", () => { - const a = fromJsonString( - proto3_ts.Proto3MessageSchema, - '{ "singular_string_field": "a" }', - ); - const b = fromJsonString( - proto3_ts.Proto3MessageSchema, - '{ "singularStringField": "b" }', - ); - - expect(a.singularStringField).toBe("a"); - expect(b.singularStringField).toBe("b"); - }); - }); describe("duplicate fields", () => { // This depends on the ECMA-262-defined JSON.parse() behavior, which is itself // specified to choose the last field value for a duplicate field.