Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FieldMask JSON read/write (snake_case <-> camelCase) is non-conforming #396

Closed
jcready opened this issue Nov 12, 2022 · 4 comments · Fixed by #552
Closed

FieldMask JSON read/write (snake_case <-> camelCase) is non-conforming #396

jcready opened this issue Nov 12, 2022 · 4 comments · Fixed by #552

Comments

@jcready
Copy link
Contributor

jcready commented Nov 12, 2022

From field_mask_util_test.cc:

TEST_F(SnakeCaseCamelCaseTest, SnakeToCamel) {
  EXPECT_EQ("fooBar", SnakeCaseToCamelCase("foo_bar"));
  EXPECT_EQ("FooBar", SnakeCaseToCamelCase("_foo_bar"));
  EXPECT_EQ("foo3Bar", SnakeCaseToCamelCase("foo3_bar"));
  // No uppercase letter is allowed.
  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("Foo"));
  // Any character after a "_" must be a lowercase letter.
  //   1. "_" cannot be followed by another "_".
  //   2. "_" cannot be followed by a digit.
  //   3. "_" cannot appear as the last character.
  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo__bar"));
  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_3bar"));
  EXPECT_EQ("#FAIL#", SnakeCaseToCamelCase("foo_bar_"));
}


TEST_F(SnakeCaseCamelCaseTest, CamelToSnake) {
  EXPECT_EQ("foo_bar", CamelCaseToSnakeCase("fooBar"));
  EXPECT_EQ("_foo_bar", CamelCaseToSnakeCase("FooBar"));
  EXPECT_EQ("foo3_bar", CamelCaseToSnakeCase("foo3Bar"));
  // "_"s are not allowed.
  EXPECT_EQ("#FAIL#", CamelCaseToSnakeCase("foo_bar"));
}

FieldMask.toJson() (snake_case -> camelCase)

The existing implementation fails tests 2 and 3 for Any character after a "_" must be a lowercase letter. as these do not throw errors:

// 2. "_" cannot be followed by a digit.
FieldMask.toJson({ paths: ['foo_3bar'] });

// 3. "_" cannot appear as the last character.
FieldMask.toJson({ paths: ['foo_bar_'] });

I believe this could trivially be fixed with the following change to packages/plugin/src/message-type-extensions/well-known-types.ts

+                 const invalidFieldMaskJsonRegex = /[A-Z]|(_([.0-9_]|$))/g;
                  return message.paths.map(p => {
-                     if (p.match(/_[0-9]?_/g) || p.match(/[A-Z]/g))
+                     if (invalidFieldMaskJsonRegex.test(p))

FieldMask.fromJson() (camelCase -> snake_case)

The existing implementation fails the second expectation:

expect(FieldMask.fromJson('FooBar')).toEqual({ paths: ['_foo_bar'] });
// Expected $.paths[0] = 'foo_bar' to equal '_foo_bar'.

This failure is purely due to this one line but the git blame is so old and part of a commit simply titled "transferring to github.com" that it has become a classic Chesterton's Fence situation.

return (sc[0] === "_") ? sc.substring(1) : sc;

Again, I believe this could be trivially fixed.

-                      return (sc[0] === "_") ? sc.substring(1) : sc;
+                      return sc; 
@hugebdu
Copy link
Contributor

hugebdu commented Jan 10, 2023

@timostamm any plans/thoughts to align it?
10x

@timostamm
Copy link
Owner

@hugebdu, we should match the C++ implementation. It's very likely that protobuf-es has the same issue.
I'm strapped for time at the moment - contributions are most welcome. It should be fairly straight-forward to replicate the test cases and go from there.

@hugebdu
Copy link
Contributor

hugebdu commented Jan 12, 2023

@timostamm
I can try submitting a PR, however that's a breaking change.
Do you want to add an option to control the field mask casing or this will be a major release?

@hugebdu
Copy link
Contributor

hugebdu commented Feb 8, 2023

@timostamm?

@jcready jcready changed the title FieldMask JSON read/write (snake_case <-> camcelCase) is non-conforming FieldMask JSON read/write (snake_case <-> camelCase) is non-conforming Feb 8, 2023
jcready added a commit to jcready/protobuf-ts that referenced this issue Jun 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants