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