]>
Commit | Line | Data |
---|---|---|
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 | */ | |
37 | IDENTITY() { | |
38 | 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's 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 | */ | |
53 | UPPER_CAMEL_CASE() { | |
54 | 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's 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 | */ | |
72 | UPPER_CAMEL_CASE_WITH_SPACES() { | |
73 | 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 a lower case field name where each word is separated by an underscore (_). | |
81 | * | |
82 | * <p>Here's 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 | LOWER_CASE_WITH_UNDERSCORES() { | |
91 | public String translateName(Field f) { | |
92 | return separateCamelCase(f.getName(), "_").toLowerCase(Locale.ENGLISH); | |
93 | } | |
94 | }, | |
95 | ||
96 | /** | |
97 | * Using this naming policy with Gson will modify the Java Field name from its camel cased | |
98 | * form to a lower case field name where each word is separated by a dash (-). | |
99 | * | |
100 | * <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p> | |
101 | * <ul> | |
102 | * <li>someFieldName ---> some-field-name</li> | |
103 | * <li>_someFieldName ---> _some-field-name</li> | |
104 | * <li>aStringField ---> a-string-field</li> | |
105 | * <li>aURL ---> a-u-r-l</li> | |
106 | * </ul> | |
107 | * Using dashes in JavaScript is not recommended since dash is also used for a minus sign in | |
108 | * expressions. This requires that a field named with dashes is always accessed as a quoted | |
109 | * property like {@code myobject['my-field']}. Accessing it as an object field | |
110 | * {@code myobject.my-field} will result in an unintended javascript expression. | |
111 | * @since 1.4 | |
112 | */ | |
113 | LOWER_CASE_WITH_DASHES() { | |
114 | public String translateName(Field f) { | |
115 | return separateCamelCase(f.getName(), "-").toLowerCase(Locale.ENGLISH); | |
116 | } | |
117 | }; | |
118 | ||
119 | /** | |
120 | * Converts the field name that uses camel-case define word separation into | |
121 | * separate words that are separated by the provided {@code separatorString}. | |
122 | */ | |
123 | private static String separateCamelCase(String name, String separator) { | |
124 | StringBuilder translation = new StringBuilder(); | |
125 | for (int i = 0; i < name.length(); i++) { | |
126 | char character = name.charAt(i); | |
127 | if (Character.isUpperCase(character) && translation.length() != 0) { | |
128 | translation.append(separator); | |
129 | } | |
130 | translation.append(character); | |
131 | } | |
132 | return translation.toString(); | |
133 | } | |
134 | ||
135 | /** | |
136 | * Ensures the JSON field names begins with an upper case letter. | |
137 | */ | |
138 | private static String upperCaseFirstLetter(String name) { | |
139 | StringBuilder fieldNameBuilder = new StringBuilder(); | |
140 | int index = 0; | |
141 | char firstCharacter = name.charAt(index); | |
142 | ||
143 | while (index < name.length() - 1) { | |
144 | if (Character.isLetter(firstCharacter)) { | |
145 | break; | |
146 | } | |
147 | ||
148 | fieldNameBuilder.append(firstCharacter); | |
149 | firstCharacter = name.charAt(++index); | |
150 | } | |
151 | ||
152 | if (index == name.length()) { | |
153 | return fieldNameBuilder.toString(); | |
154 | } | |
155 | ||
156 | if (!Character.isUpperCase(firstCharacter)) { | |
157 | String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index); | |
158 | return fieldNameBuilder.append(modifiedTarget).toString(); | |
159 | } else { | |
160 | return name; | |
161 | } | |
162 | } | |
163 | ||
164 | private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) { | |
165 | return (indexOfSubstring < srcString.length()) | |
166 | ? firstCharacter + srcString.substring(indexOfSubstring) | |
167 | : String.valueOf(firstCharacter); | |
168 | } | |
169 | } |