001 package com.nimbusds.jose.util;
002
003
004 import java.net.MalformedURLException;
005 import java.net.URL;
006 import java.text.ParseException;
007 import java.util.Arrays;
008 import java.util.List;
009
010 import net.minidev.json.JSONArray;
011 import net.minidev.json.JSONObject;
012 import net.minidev.json.parser.JSONParser;
013
014
015 /**
016 * JSON object helper methods for parsing and typed retrieval of member values.
017 *
018 * @author Vladimir Dzhuvinov
019 * @version $version$ (2013-01-08)
020 */
021 public class JSONObjectUtils {
022
023
024 /**
025 * Parses a JSON object.
026 *
027 * <p>Specific JSON to Java entity mapping (as per JSON Smart):
028 *
029 * <ul>
030 * <li>JSON true|false map to {@code java.lang.Boolean}.
031 * <li>JSON numbers map to {@code java.lang.Number}.
032 * <ul>
033 * <li>JSON integer numbers map to {@code long}.
034 * <li>JSON fraction numbers map to {@code double}.
035 * </ul>
036 * <li>JSON strings map to {@code java.lang.String}.
037 * <li>JSON arrays map to {@code net.minidev.json.JSONArray}.
038 * <li>JSON objects map to {@code net.minidev.json.JSONObject}.
039 * </ul>
040 *
041 * @param s The JSON object string to parse. Must not be {@code null}.
042 *
043 * @return The JSON object.
044 *
045 * @throws ParseException If the string cannot be parsed to a valid JSON
046 * object.
047 */
048 public static JSONObject parseJSONObject(final String s)
049 throws ParseException {
050
051 Object o = null;
052
053 try {
054 o = new JSONParser(JSONParser.USE_HI_PRECISION_FLOAT).parse(s);
055
056 } catch (net.minidev.json.parser.ParseException e) {
057
058 throw new ParseException("Invalid JSON: " + e.getMessage(), 0);
059 }
060
061 if (o instanceof JSONObject) {
062 return (JSONObject)o;
063 } else {
064 throw new ParseException("JSON entity is not an object", 0);
065 }
066 }
067
068
069 /**
070 * Gets a generic member of a JSON object.
071 *
072 * @param o The JSON object. Must not be {@code null}.
073 * @param key The JSON object member key. Must not be {@code null}.
074 * @param clazz The expected class of the JSON object member value. Must
075 * not be {@code null}.
076 *
077 * @return The JSON object member value.
078 *
079 * @throws ParseException If the value is missing, {@code null} or not
080 * of the expected type.
081 */
082 @SuppressWarnings("unchecked")
083 private static <T> T getGeneric(final JSONObject o, final String key, final Class<T> clazz)
084 throws ParseException {
085
086 if (! o.containsKey(key)) {
087 throw new ParseException("Missing JSON object member with key \"" + key + "\"", 0);
088 }
089
090 if (o.get(key) == null) {
091 throw new ParseException("JSON object member with key \"" + key + "\" has null value", 0);
092 }
093
094 Object value = o.get(key);
095
096 if (! clazz.isAssignableFrom(value.getClass())) {
097 throw new ParseException("Unexpected type of JSON object member with key \"" + key + "\"", 0);
098 }
099
100 return (T)value;
101 }
102
103
104 /**
105 * Gets a boolean member of a JSON object.
106 *
107 * @param o The JSON object. Must not be {@code null}.
108 * @param key The JSON object member key. Must not be {@code null}.
109 *
110 * @return The member value.
111 *
112 * @throws ParseException If the value is missing, {@code null} or not
113 * of the expected type.
114 */
115 public static boolean getBoolean(final JSONObject o, final String key)
116 throws ParseException {
117
118 return getGeneric(o, key, Boolean.class);
119 }
120
121
122 /**
123 * Gets an number member of a JSON object as {@code int}.
124 *
125 * @param o The JSON object. Must not be {@code null}.
126 * @param key The JSON object member key. Must not be {@code null}.
127 *
128 * @return The member value.
129 *
130 * @throws ParseException If the value is missing, {@code null} or not
131 * of the expected type.
132 */
133 public static int getInt(final JSONObject o, final String key)
134 throws ParseException {
135
136 return getGeneric(o, key, Number.class).intValue();
137 }
138
139
140 /**
141 * Gets a number member of a JSON object as {@code long}.
142 *
143 * @param o The JSON object. Must not be {@code null}.
144 * @param key The JSON object member key. Must not be {@code null}.
145 *
146 * @return The member value.
147 *
148 * @throws ParseException If the value is missing, {@code null} or not
149 * of the expected type.
150 */
151 public static long getLong(final JSONObject o, final String key)
152 throws ParseException {
153
154 return getGeneric(o, key, Number.class).longValue();
155 }
156
157
158 /**
159 * Gets a number member of a JSON object {@code float}.
160 *
161 * @param o The JSON object. Must not be {@code null}.
162 * @param key The JSON object member key. Must not be {@code null}.
163 *
164 * @return The member value.
165 *
166 * @throws ParseException If the value is missing, {@code null} or not
167 * of the expected type.
168 */
169 public static float getFloat(final JSONObject o, final String key)
170 throws ParseException {
171
172 return getGeneric(o, key, Number.class).floatValue();
173 }
174
175
176 /**
177 * Gets a number member of a JSON object as {@code double}.
178 *
179 * @param o The JSON object. Must not be {@code null}.
180 * @param key The JSON object member key. Must not be {@code null}.
181 *
182 * @return The member value.
183 *
184 * @throws ParseException If the value is missing, {@code null} or not
185 * of the expected type.
186 */
187 public static double getDouble(final JSONObject o, final String key)
188 throws ParseException {
189
190 return getGeneric(o, key, Number.class).doubleValue();
191 }
192
193
194 /**
195 * Gets a string member of a JSON object.
196 *
197 * @param o The JSON object. Must not be {@code null}.
198 * @param key The JSON object member key. Must not be {@code null}.
199 *
200 * @return The member value.
201 *
202 * @throws ParseException If the value is missing, {@code null} or not
203 * of the expected type.
204 */
205 public static String getString(final JSONObject o, final String key)
206 throws ParseException {
207
208 return getGeneric(o, key, String.class);
209 }
210
211
212 /**
213 * Gets a string member of a JSON object as {@code java.net.URL}.
214 *
215 * @param o The JSON object. Must not be {@code null}.
216 * @param key The JSON object member key. Must not be {@code null}.
217 *
218 * @return The member value.
219 *
220 * @throws ParseException If the value is missing, {@code null} or not
221 * of the expected type.
222 */
223 public static URL getURL(final JSONObject o, final String key)
224 throws ParseException {
225
226 try {
227 return new URL(getGeneric(o, key, String.class));
228
229 } catch (MalformedURLException e) {
230
231 throw new ParseException(e.getMessage(), 0);
232 }
233 }
234
235
236 /**
237 * Gets a JSON array member of a JSON object.
238 *
239 * @param o The JSON object. Must not be {@code null}.
240 * @param key The JSON object member key. Must not be {@code null}.
241 *
242 * @return The member value.
243 *
244 * @throws ParseException If the value is missing, {@code null} or not
245 * of the expected type.
246 */
247 public static JSONArray getJSONArray(final JSONObject o, final String key)
248 throws ParseException {
249
250 return getGeneric(o, key, JSONArray.class);
251 }
252
253
254 /**
255 * Gets a string array member of a JSON object.
256 *
257 * @param o The JSON object. Must not be {@code null}.
258 * @param key The JSON object member key. Must not be {@code null}.
259 *
260 * @return The member value.
261 *
262 * @throws ParseException If the value is missing, {@code null} or not
263 * of the expected type.
264 */
265 public static String[] getStringArray(final JSONObject o, final String key)
266 throws ParseException {
267
268 JSONArray jsonArray = getJSONArray(o, key);
269
270 try {
271 return jsonArray.toArray(new String[0]);
272
273 } catch (ArrayStoreException e) {
274
275 throw new ParseException("JSON object member with key \"" + key + "\" is not an array of strings", 0);
276 }
277 }
278
279 /**
280 * Gets a string list member of a JSON object
281 *
282 * @param o The JSON object. Must not be {@code null}.
283 * @param key The JSON object member key. Must not be {@code null}.
284 *
285 * @return The member value.
286 *
287 * @throws ParseException If the value is missing, {@code null} or not
288 * of the expected type.
289 */
290 public static List<String> getStringList(final JSONObject o, final String key) throws ParseException {
291
292 String[] array = getStringArray(o, key);
293
294 return Arrays.asList(array);
295
296 }
297
298 /**
299 * Gets a JSON object member of a JSON object.
300 *
301 * @param o The JSON object. Must not be {@code null}.
302 * @param key The JSON object member key. Must not be {@code null}.
303 *
304 * @return The member value.
305 *
306 * @throws ParseException If the value is missing, {@code null} or not
307 * of the expected type.
308 */
309 public static JSONObject getJSONObject(final JSONObject o, final String key)
310 throws ParseException {
311
312 return getGeneric(o, key, JSONObject.class);
313 }
314
315
316 /**
317 * Prevents public instantiation.
318 */
319 private JSONObjectUtils() {
320
321 // Nothing to do
322 }
323 }
324