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