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

fix: Use jsonName even with snakeToCamel=false. #653

Merged
merged 1 commit into from
Aug 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions src/case.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import { Options } from './options';

export function maybeSnakeToCamel(s: string, options: Pick<Options, 'snakeToCamel'>): string {
if (options.snakeToCamel.includes('keys') && s.includes('_')) {
const hasLowerCase = !!s.match(/[a-z]/);
return s
.split('_')
.map((word, i) => {
// If the word is already mixed case, leave the exist case as-is
word = hasLowerCase ? word : word.toLowerCase();
return i === 0 ? word : capitalize(word);
})
.join('');
/** Converts `key` to TS/JS camel-case idiom, unless overridden not to. */
export function maybeSnakeToCamel(key: string, options: Pick<Options, 'snakeToCamel'>): string {
if (options.snakeToCamel.includes('keys') && key.includes('_')) {
return snakeToCamel(key);
} else {
return s;
return key;
}
}

export function camelToSnake(s: string): string {
export function snakeToCamel(s: string): string {
const hasLowerCase = !!s.match(/[a-z]/);
return s
.replace(/[\w]([A-Z])/g, function (m) {
return m[0] + '_' + m[1];
.split('_')
.map((word, i) => {
// If the word is already mixed case, leave the existing case as-is
word = hasLowerCase ? word : word.toLowerCase();
return i === 0 ? word : capitalize(word);
})
.toUpperCase();
.join('');
}

export function camelToSnake(s: string): string {
return s.replace(/\w([A-Z])/g, (m) => m[0] + '_' + m[1]).toUpperCase();
}

export function capitalize(s: string): string {
Expand Down
13 changes: 10 additions & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import ReadStream = NodeJS.ReadStream;
import { SourceDescription } from './sourceInfo';
import { Options, ServiceOption } from './options';
import { camelCase } from './case';
import { camelCase, snakeToCamel } from './case';

export function protoFilesToGenerate(request: CodeGeneratorRequest): FileDescriptorProto[] {
return request.protoFile.filter((f) => request.fileToGenerate.includes(f.name));
Expand Down Expand Up @@ -174,13 +174,20 @@ export class FormattedMethodDescriptor implements MethodDescriptorProto {
}
}

export function getFieldJsonName(field: FieldDescriptorProto, options: Options): string {
export function getFieldJsonName(
field: Pick<FieldDescriptorProto, 'name' | 'jsonName'>,
options: Pick<Options, 'snakeToCamel'>
): string {
// jsonName will be camelCased by the protocol compiler, plus can be overridden by the user,
// so just use that instead of our own maybeSnakeToCamel
if (options.snakeToCamel.includes('json')) {
return field.jsonName;
} else {
return field.name;
// The user wants to keep snake case in the JSON, but we still want to see if the jsonName
// attribute is set as an explicit override.
const probableJsonName = snakeToCamel(field.name);
const isJsonNameSet = probableJsonName !== field.jsonName;
return isJsonNameSet ? field.jsonName : field.name;
}
}

Expand Down
11 changes: 11 additions & 0 deletions tests/case-test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { maybeSnakeToCamel } from '../src/case';
import { Options, optionsFromParameter } from '../src/options';
import { getFieldJsonName } from '../src/utils';

const keys = optionsFromParameter('snakeToCamel=keys');

Expand Down Expand Up @@ -45,4 +46,14 @@ describe('case', () => {
it('converts snake to camel with first underscore and camelize other', () => {
expect(maybeSnakeToCamel('_uuid_foo', { snakeToCamel: ['keys'] })).toEqual('UuidFoo');
});

describe('getFieldJsonName', () => {
it('keeps snake case when jsonName is probably not set', () => {
expect(getFieldJsonName({ name: 'foo_bar', jsonName: 'fooBar' }, { snakeToCamel: [] })).toBe('foo_bar');
});

it('uses jsonName when it is set', () => {
expect(getFieldJsonName({ name: 'foo_bar', jsonName: 'foo' }, { snakeToCamel: [] })).toBe('foo');
});
});
});