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