• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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" ---&gt; "JSON Field Name":</p>
48    * <ul>
49    *   <li>someFieldName ---&gt; SomeFieldName</li>
50    *   <li>_someFieldName ---&gt; _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" ---&gt; "JSON Field Name":</p>
65    * <ul>
66    *   <li>someFieldName ---&gt; Some Field Name</li>
67    *   <li>_someFieldName ---&gt; _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" ---&gt; "JSON Field Name":</p>
83    * <ul>
84    *   <li>someFieldName ---&gt; SOME_FIELD_NAME</li>
85    *   <li>_someFieldName ---&gt; _SOME_FIELD_NAME</li>
86    *   <li>aStringField ---&gt; A_STRING_FIELD</li>
87    *   <li>aURL ---&gt; 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" ---&gt; "JSON Field Name":</p>
103    * <ul>
104    *   <li>someFieldName ---&gt; some_field_name</li>
105    *   <li>_someFieldName ---&gt; _some_field_name</li>
106    *   <li>aStringField ---&gt; a_string_field</li>
107    *   <li>aURL ---&gt; 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" ---&gt; "JSON Field Name":</p>
121    * <ul>
122    *   <li>someFieldName ---&gt; some-field-name</li>
123    *   <li>_someFieldName ---&gt; _some-field-name</li>
124    *   <li>aStringField ---&gt; a-string-field</li>
125    *   <li>aURL ---&gt; 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" ---&gt; "JSON Field Name":</p>
145    * <ul>
146    *   <li>someFieldName ---&gt; some.field.name</li>
147    *   <li>_someFieldName ---&gt; _some.field.name</li>
148    *   <li>aStringField ---&gt; a.string.field</li>
149    *   <li>aURL ---&gt; 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