package sh.calaba.org.codehaus.jackson.map; import sh.calaba.org.codehaus.jackson.map.introspect.AnnotatedField; import sh.calaba.org.codehaus.jackson.map.introspect.AnnotatedMethod; import sh.calaba.org.codehaus.jackson.map.introspect.AnnotatedParameter; /** * Class that defines how names of JSON properties ("external names") * are derived from names of POJO methods and fields ("internal names"), * in cases where they are not * auto-detected and no explicit annotations exist for naming. * Methods are passed information about POJO member for which name is needed, * as well as default name that would be used if no custom strategy was used. *

* Default implementation returns suggested ("default") name unmodified. *

* Note that the strategy is guaranteed to be called once per logical property * (which may be represented by multiple members; such as pair of a getter and * a setter), but may be called for each: implementations should not count on * exact number of times, and should work for any member that represent a * property. *

* In absence of a registered custom strategy, default Java property naming strategy * is used, which leaves field names as is, and removes set/get/is prefix * from methods (as well as lower-cases initial sequence of capitalized * characters). * * @since 1.8 */ public abstract class PropertyNamingStrategy { /* /********************************************************** /* API /********************************************************** */ /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given field. * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param field Field used to access property * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the field represents */ public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given getter method; typically called when building a serializer. * (but not always -- when using "getter-as-setter", may be called during * deserialization) * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param method Method used to access property. * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the method represents */ public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given setter method; typically called when building a deserializer * (but not necessarily only then). * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param method Method used to access property. * @param defaultName Default name that would be used for property in absence of custom strategy * * @return Logical name to use for property that the method represents */ public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return defaultName; } /** * Method called to find external name (name used in JSON) for given logical * POJO property, * as defined by given constructor parameter; typically called when building a deserializer * (but not necessarily only then). * * @param config Configuration in used: either SerializationConfig * or DeserializationConfig, depending on whether method is called * during serialization or deserialization * @param ctorParam Constructor parameter used to pass property. * @param defaultName Default name that would be used for property in absence of custom strategy * @since 1.9 */ public String nameForConstructorParameter(MapperConfig config, AnnotatedParameter ctorParam, String defaultName) { return defaultName; } /* /********************************************************** /* Standard implementations /********************************************************** */ /** * @since 1.9 */ public static abstract class PropertyNamingStrategyBase extends PropertyNamingStrategy { @Override public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) { return translate(defaultName); } @Override public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return translate(defaultName); } @Override public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) { return translate(defaultName); } @Override public String nameForConstructorParameter(MapperConfig config, AnnotatedParameter ctorParam, String defaultName) { return translate(defaultName); } public abstract String translate(String propertyName); } /* /********************************************************** /* Standard implementations /********************************************************** */ /** * See {@link LowerCaseWithUnderscoresStrategy} for details. * * @since 1.9 */ public static final PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES = new LowerCaseWithUnderscoresStrategy(); /** * A {@link PropertyNamingStrategy} that translates typical camel case Java * property names to lower case JSON element names, separated by * underscores. This implementation is somewhat lenient, in that it * provides some additional translations beyond strictly translating from * camel case only. In particular, the following translations are applied * by this PropertyNamingStrategy. * *

* * These rules result in the following additional example translations from * Java property names to JSON element names. * * * @since 1.9 */ public static class LowerCaseWithUnderscoresStrategy extends PropertyNamingStrategyBase { @Override public String translate(String input) { if (input == null) return input; // garbage in, garbage out int length = input.length(); StringBuilder result = new StringBuilder(length * 2); int resultLength = 0; boolean wasPrevTranslated = false; for (int i = 0; i < length; i++) { char c = input.charAt(i); if (i > 0 || c != '_') // skip first starting underscore { if (Character.isUpperCase(c)) { if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') { result.append('_'); resultLength++; } c = Character.toLowerCase(c); wasPrevTranslated = true; } else { wasPrevTranslated = false; } result.append(c); resultLength++; } } return resultLength > 0 ? result.toString() : input; } } }