1 /* 2 * Copyright (C) 2008 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.gson; 18 19 import java.lang.reflect.Field; 20 import java.util.Locale; 21 22 /** 23 * An enumeration that defines a few standard naming conventions for JSON field names. 24 * This enumeration should be used in conjunction with {@link com.google.gson.GsonBuilder} 25 * to configure a {@link com.google.gson.Gson} instance to properly translate Java field 26 * names into the desired JSON field names. 27 * 28 * @author Inderjeet Singh 29 * @author Joel Leitch 30 */ 31 public enum FieldNamingPolicy implements FieldNamingStrategy { 32 33 /** 34 * Using this naming policy with Gson will ensure that the field name is 35 * unchanged. 36 */ IDENTITY()37 IDENTITY() { 38 @Override public String translateName(Field f) { 39 return f.getName(); 40 } 41 }, 42 43 /** 44 * Using this naming policy with Gson will ensure that the first "letter" of the Java 45 * field name is capitalized when serialized to its JSON form. 46 * 47 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 48 * <ul> 49 * <li>someFieldName ---> SomeFieldName</li> 50 * <li>_someFieldName ---> _SomeFieldName</li> 51 * </ul> 52 */ UPPER_CAMEL_CASE()53 UPPER_CAMEL_CASE() { 54 @Override public String translateName(Field f) { 55 return upperCaseFirstLetter(f.getName()); 56 } 57 }, 58 59 /** 60 * Using this naming policy with Gson will ensure that the first "letter" of the Java 61 * field name is capitalized when serialized to its JSON form and the words will be 62 * separated by a space. 63 * 64 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 65 * <ul> 66 * <li>someFieldName ---> Some Field Name</li> 67 * <li>_someFieldName ---> _Some Field Name</li> 68 * </ul> 69 * 70 * @since 1.4 71 */ UPPER_CAMEL_CASE_WITH_SPACES()72 UPPER_CAMEL_CASE_WITH_SPACES() { 73 @Override public String translateName(Field f) { 74 return upperCaseFirstLetter(separateCamelCase(f.getName(), ' ')); 75 } 76 }, 77 78 /** 79 * Using this naming policy with Gson will modify the Java Field name from its camel cased 80 * form to an upper case field name where each word is separated by an underscore (_). 81 * 82 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 83 * <ul> 84 * <li>someFieldName ---> SOME_FIELD_NAME</li> 85 * <li>_someFieldName ---> _SOME_FIELD_NAME</li> 86 * <li>aStringField ---> A_STRING_FIELD</li> 87 * <li>aURL ---> A_U_R_L</li> 88 * </ul> 89 * 90 * @since 2.9.0 91 */ UPPER_CASE_WITH_UNDERSCORES()92 UPPER_CASE_WITH_UNDERSCORES() { 93 @Override public String translateName(Field f) { 94 return separateCamelCase(f.getName(), '_').toUpperCase(Locale.ENGLISH); 95 } 96 }, 97 98 /** 99 * Using this naming policy with Gson will modify the Java Field name from its camel cased 100 * form to a lower case field name where each word is separated by an underscore (_). 101 * 102 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 103 * <ul> 104 * <li>someFieldName ---> some_field_name</li> 105 * <li>_someFieldName ---> _some_field_name</li> 106 * <li>aStringField ---> a_string_field</li> 107 * <li>aURL ---> a_u_r_l</li> 108 * </ul> 109 */ LOWER_CASE_WITH_UNDERSCORES()110 LOWER_CASE_WITH_UNDERSCORES() { 111 @Override public String translateName(Field f) { 112 return separateCamelCase(f.getName(), '_').toLowerCase(Locale.ENGLISH); 113 } 114 }, 115 116 /** 117 * Using this naming policy with Gson will modify the Java Field name from its camel cased 118 * form to a lower case field name where each word is separated by a dash (-). 119 * 120 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 121 * <ul> 122 * <li>someFieldName ---> some-field-name</li> 123 * <li>_someFieldName ---> _some-field-name</li> 124 * <li>aStringField ---> a-string-field</li> 125 * <li>aURL ---> a-u-r-l</li> 126 * </ul> 127 * Using dashes in JavaScript is not recommended since dash is also used for a minus sign in 128 * expressions. This requires that a field named with dashes is always accessed as a quoted 129 * property like {@code myobject['my-field']}. Accessing it as an object field 130 * {@code myobject.my-field} will result in an unintended JavaScript expression. 131 * 132 * @since 1.4 133 */ LOWER_CASE_WITH_DASHES()134 LOWER_CASE_WITH_DASHES() { 135 @Override public String translateName(Field f) { 136 return separateCamelCase(f.getName(), '-').toLowerCase(Locale.ENGLISH); 137 } 138 }, 139 140 /** 141 * Using this naming policy with Gson will modify the Java Field name from its camel cased 142 * form to a lower case field name where each word is separated by a dot (.). 143 * 144 * <p>Here are a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> 145 * <ul> 146 * <li>someFieldName ---> some.field.name</li> 147 * <li>_someFieldName ---> _some.field.name</li> 148 * <li>aStringField ---> a.string.field</li> 149 * <li>aURL ---> a.u.r.l</li> 150 * </ul> 151 * Using dots in JavaScript is not recommended since dot is also used for a member sign in 152 * expressions. This requires that a field named with dots is always accessed as a quoted 153 * property like {@code myobject['my.field']}. Accessing it as an object field 154 * {@code myobject.my.field} will result in an unintended JavaScript expression. 155 * 156 * @since 2.8.4 157 */ LOWER_CASE_WITH_DOTS()158 LOWER_CASE_WITH_DOTS() { 159 @Override public String translateName(Field f) { 160 return separateCamelCase(f.getName(), '.').toLowerCase(Locale.ENGLISH); 161 } 162 }; 163 164 /** 165 * Converts the field name that uses camel-case define word separation into 166 * separate words that are separated by the provided {@code separator}. 167 */ separateCamelCase(String name, char separator)168 static String separateCamelCase(String name, char separator) { 169 StringBuilder translation = new StringBuilder(); 170 for (int i = 0, length = name.length(); i < length; i++) { 171 char character = name.charAt(i); 172 if (Character.isUpperCase(character) && translation.length() != 0) { 173 translation.append(separator); 174 } 175 translation.append(character); 176 } 177 return translation.toString(); 178 } 179 180 /** 181 * Ensures the JSON field names begins with an upper case letter. 182 */ upperCaseFirstLetter(String s)183 static String upperCaseFirstLetter(String s) { 184 int length = s.length(); 185 for (int i = 0; i < length; i++) { 186 char c = s.charAt(i); 187 if (Character.isLetter(c)) { 188 if (Character.isUpperCase(c)) { 189 return s; 190 } 191 192 char uppercased = Character.toUpperCase(c); 193 // For leading letter only need one substring 194 if (i == 0) { 195 return uppercased + s.substring(1); 196 } else { 197 return s.substring(0, i) + uppercased + s.substring(i + 1); 198 } 199 } 200 } 201 202 return s; 203 } 204 } 205