Skip to content

Commit 3188187

Browse files
authored
added functionality for PropertyNamingStrategies.UPPER_SNAKE_CASE (#3243)
Added functionality for PropertyNamingStrategies.UPPER_SNAKE_CASE According to the feature request in the issue #3238, a new strategy has been added of giving a upper snake case. example: userName becomes USER_NAME.
1 parent cbd50d6 commit 3188187

File tree

2 files changed

+137
-23
lines changed

2 files changed

+137
-23
lines changed

src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategies.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ public abstract class PropertyNamingStrategies
5353
*/
5454
public static final PropertyNamingStrategy SNAKE_CASE = new SnakeCaseStrategy();
5555

56+
/**
57+
* Naming convention in which the words are in upper-case letters, separated by underscores.
58+
* See {@link UpperSnakeCaseStrategy} for details.
59+
* @since 2.13
60+
* <p>
61+
*/
62+
public static final PropertyNamingStrategy UPPER_SNAKE_CASE = new UpperSnakeCaseStrategy();
63+
5664
/**
5765
* Naming convention in which all words of the logical name are in lower case, and
5866
* no separator is used between words.
@@ -79,7 +87,7 @@ public abstract class PropertyNamingStrategies
7987
* Example external property names would be "number.value", "naming.strategy", "the.definite.proof".
8088
*/
8189
public static final PropertyNamingStrategy LOWER_DOT_CASE = new LowerDotCaseStrategy();
82-
90+
8391
/*
8492
/**********************************************************************
8593
/* Public base class for simple implementations
@@ -159,7 +167,7 @@ protected String translateLowerCaseWithSeparator(final String input, final char
159167

160168
/*
161169
/**********************************************************************
162-
/* Standard implementations
170+
/* Standard implementations
163171
/**********************************************************************
164172
*/
165173

@@ -207,7 +215,7 @@ protected String translateLowerCaseWithSeparator(final String input, final char
207215
* <li>&quot;USER&quot; is translated to &quot;user&quot;</li>
208216
* <li>&quot;_user&quot; is translated to &quot;user&quot;</li>
209217
* <li>&quot;_User&quot; is translated to &quot;user&quot;</li>
210-
* <li>&quot;__user&quot; is translated to &quot;_user&quot;
218+
* <li>&quot;__user&quot; is translated to &quot;_user&quot;
211219
* (the first of two underscores was removed)</li>
212220
* <li>&quot;user__name&quot; is translated to &quot;user__name&quot;
213221
* (unchanged, with two underscores)</li></ul>
@@ -251,6 +259,23 @@ public String translate(String input)
251259
}
252260
}
253261

262+
/**
263+
* A {@link PropertyNamingStrategy} that translates an input to the equivalent upper case snake
264+
* case. The class extends {@link PropertyNamingStrategies.SnakeCaseStrategy} to retain the
265+
* snake case conversion functionality offered by the strategy.
266+
* @since 2.13
267+
*/
268+
public static class UpperSnakeCaseStrategy extends SnakeCaseStrategy {
269+
270+
@Override
271+
public String translate(String input) {
272+
String output = super.translate(input);
273+
if (output == null)
274+
return null;
275+
return super.translate(input).toUpperCase();
276+
}
277+
}
278+
254279
/**
255280
* "No-operation" strategy that is equivalent to not specifying any
256281
* strategy: will simply return suggested standard bean naming as-is.

src/test/java/com/fasterxml/jackson/databind/introspect/TestNamingStrategyStd.java

Lines changed: 109 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ static class Acronyms
2424
public String WWW;
2525
public String someURL;
2626
public String someURIs;
27-
27+
2828
public Acronyms() {this(null, null, null);}
2929
public Acronyms(String WWW, String someURL, String someURIs)
3030
{
@@ -33,7 +33,7 @@ public Acronyms(String WWW, String someURL, String someURIs)
3333
this.someURIs = someURIs;
3434
}
3535
}
36-
36+
3737
@JsonPropertyOrder({"from_user", "user", "from$user", "from7user", "_x"})
3838
static class UnchangedNames
3939
{
@@ -43,7 +43,7 @@ static class UnchangedNames
4343
public String from7user;
4444
// Used to test "_", but it's explicitly deprecated in JDK8 so...
4545
public String _x;
46-
46+
4747
public UnchangedNames() {this(null, null, null, null, null);}
4848
public UnchangedNames(String from_user, String _user, String from$user, String from7user, String _x)
4949
{
@@ -84,7 +84,7 @@ static class BoringBean {
8484
public String firstName = "Bob";
8585
public String lastName = "Burger";
8686
}
87-
87+
8888
public static class ClassWithObjectNodeField {
8989
public String id;
9090
public ObjectNode json;
@@ -206,21 +206,80 @@ protected SnakeNameBean(@Name("id") String id,
206206
{"xCoordinate", "x_coordinate" },
207207
});
208208

209+
final static List<Object[]> UPPER_SNAKE_CASE_NAME_TRANSLATIONS = Arrays.asList(new Object[][] {
210+
{null, null},
211+
{"", ""},
212+
{"a", "A"},
213+
{"abc", "ABC"},
214+
{"1", "1"},
215+
{"123", "123"},
216+
{"1a", "1A"},
217+
{"a1", "A1"},
218+
{"$", "$"},
219+
{"$a", "$A"},
220+
{"a$", "A$"},
221+
{"$_a", "$_A"},
222+
{"a_$", "A_$"},
223+
{"a$a", "A$A"},
224+
{"$A", "$_A"},
225+
{"$_A", "$_A"},
226+
{"_", "_"},
227+
{"__", "_"},
228+
{"___", "__"},
229+
{"A", "A"},
230+
{"A1", "A1"},
231+
{"1A", "1_A"},
232+
{"_a", "A"},
233+
{"_A", "A"},
234+
{"a_a", "A_A"},
235+
{"a_A", "A_A"},
236+
{"A_A", "A_A"},
237+
{"A_a", "A_A"},
238+
{"WWW", "WWW"},
239+
{"someURI", "SOME_URI"},
240+
{"someURIs", "SOME_URIS"},
241+
{"Results", "RESULTS"},
242+
{"_Results", "RESULTS"},
243+
{"_results", "RESULTS"},
244+
{"__results", "_RESULTS"},
245+
{"__Results", "_RESULTS"},
246+
{"___results", "__RESULTS"},
247+
{"___Results", "__RESULTS"},
248+
{"userName", "USER_NAME"},
249+
{"user_name", "USER_NAME"},
250+
{"user__name", "USER__NAME"},
251+
{"UserName", "USER_NAME"},
252+
{"User_Name", "USER_NAME"},
253+
{"User__Name", "USER__NAME"},
254+
{"_user_name", "USER_NAME"},
255+
{"_UserName", "USER_NAME"},
256+
{"_User_Name", "USER_NAME"},
257+
{"USER_NAME", "USER_NAME"},
258+
{"_Bars", "BARS" },
259+
{"usId", "US_ID" },
260+
{"uId", "U_ID" },
261+
{"xCoordinate", "X_COORDINATE" },
262+
});
263+
209264
private final ObjectMapper VANILLA_MAPPER = newJsonMapper();
210265

211-
private final ObjectMapper _lcWithUndescoreMapper = JsonMapper.builder()
266+
private final ObjectMapper _lcWithUnderscoreMapper = JsonMapper.builder()
212267
.propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
213268
.build();
214269

270+
private final ObjectMapper _ucWithUnderscoreMapper = JsonMapper.builder()
271+
.propertyNamingStrategy(PropertyNamingStrategies.UPPER_SNAKE_CASE)
272+
.build();
273+
215274
/*
216275
/**********************************************************
217276
/* Test methods for SNAKE_CASE
218277
/**********************************************************
219278
*/
220279

221280
/**
222-
* Unit test to verify translations of
223-
* {@link PropertyNamingStrategies#SNAKE_CASE}
281+
* Unit test to verify translations of
282+
* {@link PropertyNamingStrategies#SNAKE_CASE}
224283
* outside the context of an ObjectMapper.
225284
*/
226285
public void testLowerCaseStrategyStandAlone()
@@ -235,11 +294,11 @@ public void testLowerCaseStrategyStandAlone()
235294
public void testLowerCaseTranslations() throws Exception
236295
{
237296
// First serialize
238-
String json = _lcWithUndescoreMapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42));
297+
String json = _lcWithUnderscoreMapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42));
239298
assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json);
240-
299+
241300
// then deserialize
242-
PersonBean result = _lcWithUndescoreMapper.readValue(json, PersonBean.class);
301+
PersonBean result = _lcWithUnderscoreMapper.readValue(json, PersonBean.class);
243302
assertEquals("Joe", result.firstName);
244303
assertEquals("Sixpack", result.lastName);
245304
assertEquals(42, result.age);
@@ -248,11 +307,11 @@ public void testLowerCaseTranslations() throws Exception
248307
public void testLowerCaseAcronymsTranslations() throws Exception
249308
{
250309
// First serialize
251-
String json = _lcWithUndescoreMapper.writeValueAsString(new Acronyms("world wide web", "http://jackson.codehaus.org", "/path1/,/path2/"));
310+
String json = _lcWithUnderscoreMapper.writeValueAsString(new Acronyms("world wide web", "http://jackson.codehaus.org", "/path1/,/path2/"));
252311
assertEquals("{\"www\":\"world wide web\",\"some_url\":\"http://jackson.codehaus.org\",\"some_uris\":\"/path1/,/path2/\"}", json);
253-
312+
254313
// then deserialize
255-
Acronyms result = _lcWithUndescoreMapper.readValue(json, Acronyms.class);
314+
Acronyms result = _lcWithUnderscoreMapper.readValue(json, Acronyms.class);
256315
assertEquals("world wide web", result.WWW);
257316
assertEquals("http://jackson.codehaus.org", result.someURL);
258317
assertEquals("/path1/,/path2/", result.someURIs);
@@ -261,11 +320,11 @@ public void testLowerCaseAcronymsTranslations() throws Exception
261320
public void testLowerCaseOtherNonStandardNamesTranslations() throws Exception
262321
{
263322
// First serialize
264-
String json = _lcWithUndescoreMapper.writeValueAsString(new OtherNonStandardNames("Results", "_User", "___", "$User"));
323+
String json = _lcWithUnderscoreMapper.writeValueAsString(new OtherNonStandardNames("Results", "_User", "___", "$User"));
265324
assertEquals("{\"results\":\"Results\",\"user\":\"_User\",\"__\":\"___\",\"$_user\":\"$User\"}", json);
266-
325+
267326
// then deserialize
268-
OtherNonStandardNames result = _lcWithUndescoreMapper.readValue(json, OtherNonStandardNames.class);
327+
OtherNonStandardNames result = _lcWithUnderscoreMapper.readValue(json, OtherNonStandardNames.class);
269328
assertEquals("Results", result.Results);
270329
assertEquals("_User", result._User);
271330
assertEquals("___", result.___);
@@ -275,27 +334,57 @@ public void testLowerCaseOtherNonStandardNamesTranslations() throws Exception
275334
public void testLowerCaseUnchangedNames() throws Exception
276335
{
277336
// First serialize
278-
String json = _lcWithUndescoreMapper.writeValueAsString(new UnchangedNames("from_user", "_user", "from$user", "from7user", "_x"));
337+
String json = _lcWithUnderscoreMapper.writeValueAsString(new UnchangedNames("from_user", "_user", "from$user", "from7user", "_x"));
279338
assertEquals("{\"from_user\":\"from_user\",\"user\":\"_user\",\"from$user\":\"from$user\",\"from7user\":\"from7user\",\"x\":\"_x\"}", json);
280339

281340
// then deserialize
282-
UnchangedNames result = _lcWithUndescoreMapper.readValue(json, UnchangedNames.class);
341+
UnchangedNames result = _lcWithUnderscoreMapper.readValue(json, UnchangedNames.class);
283342
assertEquals("from_user", result.from_user);
284343
assertEquals("_user", result._user);
285344
assertEquals("from$user", result.from$user);
286345
assertEquals("from7user", result.from7user);
287346
assertEquals("_x", result._x);
288347
}
289348

349+
/*
350+
/**********************************************************
351+
/* Test methods for UPPER_SNAKE_CASE
352+
/**********************************************************
353+
*/
354+
355+
public void testUpperSnakeCaseStrategyStandAlone()
356+
{
357+
for (Object[] pair : UPPER_SNAKE_CASE_NAME_TRANSLATIONS) {
358+
String translatedJavaName = PropertyNamingStrategies.UPPER_SNAKE_CASE
359+
.nameForField(null, null, (String) pair[0]);
360+
assertEquals((String) pair[1], translatedJavaName);
361+
}
362+
}
363+
364+
public void testUpperSnakeCaseTranslations() throws Exception
365+
{
366+
// First serialize
367+
String json = _ucWithUnderscoreMapper
368+
.writeValueAsString(new PersonBean("Joe", "Sixpack", 42));
369+
assertEquals("{\"FIRST_NAME\":\"Joe\",\"LAST_NAME\":\"Sixpack\",\"AGE\":42}", json);
370+
371+
// then deserialize
372+
PersonBean result = _ucWithUnderscoreMapper.readValue(json, PersonBean.class);
373+
assertEquals("Joe", result.firstName);
374+
assertEquals("Sixpack", result.lastName);
375+
assertEquals(42, result.age);
376+
}
377+
378+
290379
/*
291380
/**********************************************************
292381
/* Test methods for UPPER_CAMEL_CASE
293382
/**********************************************************
294383
*/
295384

296385
/**
297-
* Unit test to verify translations of
298-
* {@link PropertyNamingStrategies#UPPER_CAMEL_CASE }
386+
* Unit test to verify translations of
387+
* {@link PropertyNamingStrategies#UPPER_CAMEL_CASE }
299388
* outside the context of an ObjectMapper.
300389
*/
301390
public void testPascalCaseStandAlone()

0 commit comments

Comments
 (0)