package com.fasterxml.jackson.databind.introspect; | |
import java.util.Arrays; | |
import java.util.List; | |
import com.fasterxml.jackson.annotation.*; | |
import com.fasterxml.jackson.databind.*; | |
import com.fasterxml.jackson.databind.annotation.JsonNaming; | |
import com.fasterxml.jackson.databind.introspect.TestNamingStrategyCustom.PersonBean; | |
import com.fasterxml.jackson.databind.node.ObjectNode; | |
/** | |
* Unit tests to verify functioning of standard {@link PropertyNamingStrategy} | |
* implementations Jackson includes out of the box. | |
*/ | |
public class TestNamingStrategyStd extends BaseMapTest | |
{ | |
@JsonPropertyOrder({"www", "some_url", "some_uris"}) | |
static class Acronyms | |
{ | |
public String WWW; | |
public String someURL; | |
public String someURIs; | |
public Acronyms() {this(null, null, null);} | |
public Acronyms(String WWW, String someURL, String someURIs) | |
{ | |
this.WWW = WWW; | |
this.someURL = someURL; | |
this.someURIs = someURIs; | |
} | |
} | |
@JsonPropertyOrder({"from_user", "user", "from$user", "from7user", "_x"}) | |
static class UnchangedNames | |
{ | |
public String from_user; | |
public String _user; | |
public String from$user; | |
public String from7user; | |
// Used to test "_", but it's explicitly deprecated in JDK8 so... | |
public String _x; | |
public UnchangedNames() {this(null, null, null, null, null);} | |
public UnchangedNames(String from_user, String _user, String from$user, String from7user, String _x) | |
{ | |
this.from_user = from_user; | |
this._user = _user; | |
this.from$user = from$user; | |
this.from7user = from7user; | |
this._x = _x; | |
} | |
} | |
@JsonPropertyOrder({"results", "user", "__", "$_user"}) | |
static class OtherNonStandardNames | |
{ | |
public String Results; | |
public String _User; | |
public String ___; | |
public String $User; | |
public OtherNonStandardNames() {this(null, null, null, null);} | |
public OtherNonStandardNames(String Results, String _User, String ___, String $User) | |
{ | |
this.Results = Results; | |
this._User = _User; | |
this.___ = ___; | |
this.$User = $User; | |
} | |
} | |
static class Bean428 { | |
@JsonProperty("fooBar") | |
public String whatever() {return "";} | |
} | |
@JsonPropertyOrder({ "firstName", "lastName" }) | |
@JsonNaming(PropertyNamingStrategy.LowerCaseStrategy.class) | |
static class BoringBean { | |
public String firstName = "Bob"; | |
public String lastName = "Burger"; | |
} | |
public static class ClassWithObjectNodeField { | |
public String id; | |
public ObjectNode json; | |
} | |
static class ExplicitBean { | |
@JsonProperty("firstName") | |
String userFirstName = "Peter"; | |
@JsonProperty("lastName") | |
String userLastName = "Venkman"; | |
@JsonProperty | |
String userAge = "35"; | |
} | |
@JsonNaming() | |
static class DefaultNaming { | |
public int someValue = 3; | |
} | |
static class FirstNameBean { | |
public String firstName; | |
protected FirstNameBean() { } | |
public FirstNameBean(String n) { firstName = n; } | |
} | |
/* | |
/********************************************************** | |
/* Set up | |
/********************************************************** | |
*/ | |
final static List<Object[]> SNAKE_CASE_NAME_TRANSLATIONS = Arrays.asList(new Object[][] { | |
{null, null}, | |
{"", ""}, | |
{"a", "a"}, | |
{"abc", "abc"}, | |
{"1", "1"}, | |
{"123", "123"}, | |
{"1a", "1a"}, | |
{"a1", "a1"}, | |
{"$", "$"}, | |
{"$a", "$a"}, | |
{"a$", "a$"}, | |
{"$_a", "$_a"}, | |
{"a_$", "a_$"}, | |
{"a$a", "a$a"}, | |
{"$A", "$_a"}, | |
{"$_A", "$_a"}, | |
{"_", "_"}, | |
{"__", "_"}, | |
{"___", "__"}, | |
{"A", "a"}, | |
{"A1", "a1"}, | |
{"1A", "1_a"}, | |
{"_a", "a"}, | |
{"_A", "a"}, | |
{"a_a", "a_a"}, | |
{"a_A", "a_a"}, | |
{"A_A", "a_a"}, | |
{"A_a", "a_a"}, | |
{"WWW", "www"}, | |
{"someURI", "some_uri"}, | |
{"someURIs", "some_uris"}, | |
{"Results", "results"}, | |
{"_Results", "results"}, | |
{"_results", "results"}, | |
{"__results", "_results"}, | |
{"__Results", "_results"}, | |
{"___results", "__results"}, | |
{"___Results", "__results"}, | |
{"userName", "user_name"}, | |
{"user_name", "user_name"}, | |
{"user__name", "user__name"}, | |
{"UserName", "user_name"}, | |
{"User_Name", "user_name"}, | |
{"User__Name", "user__name"}, | |
{"_user_name", "user_name"}, | |
{"_UserName", "user_name"}, | |
{"_User_Name", "user_name"}, | |
{"UGLY_NAME", "ugly_name"}, | |
{"_Bars", "bars" }, | |
// [databind#1026] | |
{"usId", "us_id" }, | |
{"uId", "u_id" }, | |
// [databind#2267] | |
{"xCoordinate", "x_coordinate" }, | |
}); | |
private ObjectMapper _lcWithUndescoreMapper; | |
@Override | |
public void setUp() throws Exception | |
{ | |
super.setUp(); | |
_lcWithUndescoreMapper = new ObjectMapper(); | |
_lcWithUndescoreMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); | |
} | |
/* | |
/********************************************************** | |
/* Test methods for SNAKE_CASE | |
/********************************************************** | |
*/ | |
/** | |
* Unit test to verify translations of | |
* {@link PropertyNamingStrategy#SNAKE_CASE} | |
* outside the context of an ObjectMapper. | |
*/ | |
public void testLowerCaseStrategyStandAlone() | |
{ | |
for (Object[] pair : SNAKE_CASE_NAME_TRANSLATIONS) { | |
String translatedJavaName = PropertyNamingStrategy.SNAKE_CASE.nameForField(null, null, | |
(String) pair[0]); | |
assertEquals((String) pair[1], translatedJavaName); | |
} | |
} | |
public void testLowerCaseTranslations() throws Exception | |
{ | |
// First serialize | |
String json = _lcWithUndescoreMapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42)); | |
assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json); | |
// then deserialize | |
PersonBean result = _lcWithUndescoreMapper.readValue(json, PersonBean.class); | |
assertEquals("Joe", result.firstName); | |
assertEquals("Sixpack", result.lastName); | |
assertEquals(42, result.age); | |
} | |
public void testLowerCaseAcronymsTranslations() throws Exception | |
{ | |
// First serialize | |
String json = _lcWithUndescoreMapper.writeValueAsString(new Acronyms("world wide web", "http://jackson.codehaus.org", "/path1/,/path2/")); | |
assertEquals("{\"www\":\"world wide web\",\"some_url\":\"http://jackson.codehaus.org\",\"some_uris\":\"/path1/,/path2/\"}", json); | |
// then deserialize | |
Acronyms result = _lcWithUndescoreMapper.readValue(json, Acronyms.class); | |
assertEquals("world wide web", result.WWW); | |
assertEquals("http://jackson.codehaus.org", result.someURL); | |
assertEquals("/path1/,/path2/", result.someURIs); | |
} | |
public void testLowerCaseOtherNonStandardNamesTranslations() throws Exception | |
{ | |
// First serialize | |
String json = _lcWithUndescoreMapper.writeValueAsString(new OtherNonStandardNames("Results", "_User", "___", "$User")); | |
assertEquals("{\"results\":\"Results\",\"user\":\"_User\",\"__\":\"___\",\"$_user\":\"$User\"}", json); | |
// then deserialize | |
OtherNonStandardNames result = _lcWithUndescoreMapper.readValue(json, OtherNonStandardNames.class); | |
assertEquals("Results", result.Results); | |
assertEquals("_User", result._User); | |
assertEquals("___", result.___); | |
assertEquals("$User", result.$User); | |
} | |
public void testLowerCaseUnchangedNames() throws Exception | |
{ | |
// First serialize | |
String json = _lcWithUndescoreMapper.writeValueAsString(new UnchangedNames("from_user", "_user", "from$user", "from7user", "_x")); | |
assertEquals("{\"from_user\":\"from_user\",\"user\":\"_user\",\"from$user\":\"from$user\",\"from7user\":\"from7user\",\"x\":\"_x\"}", json); | |
// then deserialize | |
UnchangedNames result = _lcWithUndescoreMapper.readValue(json, UnchangedNames.class); | |
assertEquals("from_user", result.from_user); | |
assertEquals("_user", result._user); | |
assertEquals("from$user", result.from$user); | |
assertEquals("from7user", result.from7user); | |
assertEquals("_x", result._x); | |
} | |
/* | |
/********************************************************** | |
/* Test methods for UPPER_CAMEL_CASE | |
/********************************************************** | |
*/ | |
/** | |
* Unit test to verify translations of | |
* {@link PropertyNamingStrategy#UPPER_CAMEL_CASE } | |
* outside the context of an ObjectMapper. | |
*/ | |
public void testPascalCaseStandAlone() | |
{ | |
assertEquals("UserName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "userName")); | |
assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "User")); | |
assertEquals("User", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "user")); | |
assertEquals("X", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "x")); | |
assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForField(null, null, "bADPublicName")); | |
assertEquals("BADPublicName", PropertyNamingStrategy.UPPER_CAMEL_CASE.nameForGetterMethod(null, null, "bADPublicName")); | |
} | |
// [databind#428] | |
public void testIssue428PascalWithOverrides() throws Exception | |
{ | |
String json = new ObjectMapper() | |
.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE) | |
.writeValueAsString(new Bean428()); | |
if (!json.contains(quote("fooBar"))) { | |
fail("Should use name 'fooBar', does not: "+json); | |
} | |
} | |
/* | |
/********************************************************** | |
/* Test methods for LOWER_CASE | |
/********************************************************** | |
*/ | |
// For [databind#461] | |
public void testSimpleLowerCase() throws Exception | |
{ | |
final BoringBean input = new BoringBean(); | |
ObjectMapper m = objectMapper(); | |
assertEquals(aposToQuotes("{'firstname':'Bob','lastname':'Burger'}"), | |
m.writeValueAsString(input)); | |
} | |
/* | |
/********************************************************** | |
/* Test methods for KEBAB_CASE | |
/********************************************************** | |
*/ | |
public void testKebabCaseStrategyStandAlone() | |
{ | |
assertEquals("some-value", | |
PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "someValue")); | |
assertEquals("some-value", | |
PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "SomeValue")); | |
assertEquals("url", | |
PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "URL")); | |
assertEquals("url-stuff", | |
PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "URLStuff")); | |
assertEquals("some-url-stuff", | |
PropertyNamingStrategy.KEBAB_CASE.nameForField(null, null, "SomeURLStuff")); | |
} | |
public void testSimpleKebabCase() throws Exception | |
{ | |
final FirstNameBean input = new FirstNameBean("Bob"); | |
ObjectMapper m = new ObjectMapper() | |
.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE); | |
assertEquals(aposToQuotes("{'first-name':'Bob'}"), m.writeValueAsString(input)); | |
FirstNameBean result = m.readValue(aposToQuotes("{'first-name':'Billy'}"), | |
FirstNameBean.class); | |
assertEquals("Billy", result.firstName); | |
} | |
/* | |
/********************************************************** | |
/* Test methods, other | |
/********************************************************** | |
*/ | |
/** | |
* Test [databind#815], problems with ObjectNode, naming strategy | |
*/ | |
public void testNamingWithObjectNode() throws Exception | |
{ | |
ObjectMapper m = new ObjectMapper() | |
.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE); | |
ClassWithObjectNodeField result = | |
m.readValue( | |
"{ \"id\": \"1\", \"json\": { \"foo\": \"bar\", \"baz\": \"bing\" } }", | |
ClassWithObjectNodeField.class); | |
assertNotNull(result); | |
assertEquals("1", result.id); | |
assertNotNull(result.json); | |
assertEquals(2, result.json.size()); | |
assertEquals("bing", result.json.path("baz").asText()); | |
} | |
public void testExplicitRename() throws Exception | |
{ | |
ObjectMapper m = new ObjectMapper(); | |
m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); | |
m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); | |
// by default, renaming will not take place on explicitly named fields | |
assertEquals(aposToQuotes("{'firstName':'Peter','lastName':'Venkman','user_age':'35'}"), | |
m.writeValueAsString(new ExplicitBean())); | |
m = new ObjectMapper(); | |
m.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); | |
m.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); | |
m.enable(MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING); | |
// w/ feature enabled, ALL property names should get re-written | |
assertEquals(aposToQuotes("{'first_name':'Peter','last_name':'Venkman','user_age':'35'}"), | |
m.writeValueAsString(new ExplicitBean())); | |
// test deserialization as well | |
ExplicitBean bean = | |
m.readValue(aposToQuotes("{'first_name':'Egon','last_name':'Spengler','user_age':'32'}"), | |
ExplicitBean.class); | |
assertNotNull(bean); | |
assertEquals("Egon", bean.userFirstName); | |
assertEquals("Spengler", bean.userLastName); | |
assertEquals("32", bean.userAge); | |
} | |
// Also verify that "no naming strategy" should be ok | |
public void testExplicitNoNaming() throws Exception | |
{ | |
ObjectMapper mapper = objectMapper(); | |
String json = mapper.writeValueAsString(new DefaultNaming()); | |
assertEquals(aposToQuotes("{'someValue':3}"), json); | |
} | |
} |