001/*
002 * oauth2-oidc-sdk
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.oauth2.sdk.util;
019
020
021import com.nimbusds.jose.jwk.JWKSet;
022import com.nimbusds.jwt.JWTClaimsSet;
023import com.nimbusds.oauth2.sdk.ParseException;
024import net.minidev.json.JSONArray;
025import net.minidev.json.JSONObject;
026
027import java.net.MalformedURLException;
028import java.net.URI;
029import java.net.URISyntaxException;
030import java.net.URL;
031import java.util.*;
032
033
034/**
035 * JSON object helper methods for parsing and typed retrieval of member values.
036 */
037public final class JSONObjectUtils {
038        
039        
040        /**
041         * Returns {@code true} if the JSON object is defined and contains the 
042         * specified key.
043         *
044         * @param jsonObject The JSON object to check. May be {@code null}.
045         * @param key        The key to check. Must not be {@code null}.
046         *
047         * @return {@code true} if the JSON object is defined and contains the
048         *         specified key, else {@code false}.
049         */
050        public static boolean containsKey(final JSONObject jsonObject, final String key) {
051
052                return jsonObject != null && jsonObject.containsKey(key);
053        }
054        
055        
056        /**
057         * Parses a JSON object.
058         *
059         * <p>Specific JSON to Java entity mapping (as per JSON Simple):
060         *
061         * <ul>
062         *     <li>JSON numbers mapped to {@code java.lang.Number}.
063         *     <li>JSON integer numbers mapped to {@code long}.
064         *     <li>JSON fraction numbers mapped to {@code double}.
065         * </ul>
066         *
067         * @param s The JSON object string to parse. Must not be {@code null}.
068         *
069         * @return The JSON object.
070         *
071         * @throws ParseException If the string cannot be parsed to a JSON 
072         *                        object.
073         */
074        public static JSONObject parse(final String s)
075                throws ParseException {
076                
077                Object o = JSONUtils.parseJSON(s);
078                
079                if (o instanceof JSONObject)
080                        return (JSONObject)o;
081                else
082                        throw new ParseException("The JSON entity is not an object");
083        }
084        
085        
086        /**
087         * Parses a JSON object while keeping the order of JSON object members.
088         *
089         * <p>Specific JSON to Java entity mapping (as per JSON Simple):
090         *
091         * <ul>
092         *     <li>JSON numbers mapped to {@code java.lang.Number}.
093         *     <li>JSON integer numbers mapped to {@code long}.
094         *     <li>JSON fraction numbers mapped to {@code double}.
095         * </ul>
096         *
097         * @param s The JSON object string to parse. Must not be {@code null}.
098         *
099         * @return The JSON object as linked hash map.
100         *
101         * @throws ParseException If the string cannot be parsed to a JSON
102         *                        object.
103         */
104        public static LinkedHashMap<String,Object> parseKeepingOrder(final String s)
105                throws ParseException {
106                
107                Object o = JSONUtils.parseJSONKeepingOrder(s);
108                
109                if (o instanceof LinkedHashMap)
110                        return (LinkedHashMap<String,Object>)o;
111                else
112                        throw new ParseException("The JSON entity is not an object");
113        }
114
115
116        /**
117         * Use {@link #parse(String)} instead.
118         *
119         * @param s The JSON object string to parse. Must not be {@code null}.
120         *
121         * @return The JSON object.
122         *
123         * @throws ParseException If the string cannot be parsed to a JSON
124         *                        object.
125         */
126        @Deprecated
127        public static JSONObject parseJSONObject(final String s)
128                throws ParseException {
129
130                return parse(s);
131        }
132        
133        
134        /**
135         * Gets a generic member of a JSON object.
136         *
137         * @param o     The JSON object. Must not be {@code null}.
138         * @param key   The JSON object member key. Must not be {@code null}.
139         * @param clazz The expected class of the JSON object member value.
140         *              Must not be {@code null}.
141         *
142         * @return The JSON object member value.
143         *
144         * @throws ParseException If the value is missing, {@code null} or not
145         *                        of the expected type.
146         */
147        public static <T> T getGeneric(final JSONObject o, final String key, final Class<T> clazz)
148                throws ParseException {
149        
150                if (! o.containsKey(key))
151                        throw new ParseException("Missing JSON object member with key " + key);
152                
153                Object value = o.get(key);
154                
155                if (value == null) {
156                        throw new ParseException("JSON object member with key " + key + " has null value");
157                }
158                
159                try {
160                        return JSONUtils.to(value, clazz);
161                } catch (ParseException e) {
162                        throw new ParseException("Unexpected type of JSON object member with key " + key, e);
163                }
164        }
165
166
167        /**
168         * Gets a boolean member of a JSON object.
169         *
170         * @param o   The JSON object. Must not be {@code null}.
171         * @param key The JSON object member key. Must not be {@code null}.
172         *
173         * @return The member value.
174         *
175         * @throws ParseException If the value is missing, {@code null} or not
176         *                        of the expected type.
177         */
178        public static boolean getBoolean(final JSONObject o, final String key)
179                throws ParseException {
180                
181                return getGeneric(o, key, Boolean.class);
182        }
183
184
185        /**
186         * Gets a boolean member of a JSON object.
187         *
188         * @param o   The JSON object. Must not be {@code null}.
189         * @param key The JSON object member key. Must not be {@code null}.
190         * @param def The default value to return if the key is not present or.
191         *            the value is {@code null}. May be {@code null}.
192         *
193         * @return The member value.
194         *
195         * @throws ParseException If the value is not of the expected type.
196         */
197        public static boolean getBoolean(final JSONObject o, final String key, final boolean def)
198                throws ParseException {
199                
200                if (o.get(key) != null) {
201                        return getBoolean(o, key);
202                }
203                
204                return def;
205        }
206        
207        
208        /**
209         * Gets an number member of a JSON object as {@code int}.
210         *
211         * @param o   The JSON object. Must not be {@code null}.
212         * @param key The JSON object member key. Must not be {@code null}.
213         *
214         * @return The member value.
215         *
216         * @throws ParseException If the value is missing, {@code null} or not
217         *                        of the expected type.
218         */
219        public static int getInt(final JSONObject o, final String key)
220                throws ParseException {
221                
222                return getGeneric(o, key, Number.class).intValue();     
223        }
224        
225        
226        /**
227         * Gets an number member of a JSON object as {@code int}.
228         *
229         * @param o   The JSON object. Must not be {@code null}.
230         * @param key The JSON object member key. Must not be {@code null}.
231         * @param def The default value to return if the key is not present or
232         *            the value is {@code null}.
233         *
234         * @return The member value.
235         *
236         * @throws ParseException If the value is not of the expected type.
237         */
238        public static int getInt(final JSONObject o, final String key, final int def)
239                throws ParseException {
240                
241                if (o.get(key) != null) {
242                        return getInt(o, key);
243                }
244                
245                return def;
246        }
247        
248        
249        /**
250         * Gets a number member of a JSON object as {@code long}.
251         *
252         * @param o   The JSON object. Must not be {@code null}.
253         * @param key The JSON object member key. Must not be {@code null}.
254         *
255         * @return The member value.
256         *
257         * @throws ParseException If the value is missing, {@code null} or not
258         *                        of the expected type.
259         */
260        public static long getLong(final JSONObject o, final String key)
261                throws ParseException {
262                
263                return getGeneric(o, key, Number.class).longValue();
264        }
265        
266        
267        /**
268         * Gets a number member of a JSON object as {@code long}.
269         *
270         * @param o   The JSON object. Must not be {@code null}.
271         * @param key The JSON object member key. Must not be {@code null}.
272         * @param def The default value to return if the key is not present or
273         *            the value is {@code null}.
274         *
275         * @return The member value.
276         *
277         * @throws ParseException If the value is not of the expected type.
278         */
279        public static long getLong(final JSONObject o, final String key, final long def)
280                throws ParseException {
281                
282                if (o.get(key) != null) {
283                        return getLong(o, key);
284                }
285                
286                return def;
287        }
288        
289        
290        /**
291         * Gets a number member of a JSON object {@code float}.
292         *
293         * @param o   The JSON object. Must not be {@code null}.
294         * @param key The JSON object member key. Must not be {@code null}.
295         *
296         * @return The member value.
297         *
298         * @throws ParseException If the value is missing, {@code null} or not
299         *                        of the expected type.
300         */
301        public static float getFloat(final JSONObject o, final String key)
302                throws ParseException {
303                
304                return getGeneric(o, key, Number.class).floatValue();
305        }
306        
307        
308        /**
309         * Gets a number member of a JSON object {@code float}.
310         *
311         * @param o   The JSON object. Must not be {@code null}.
312         * @param key The JSON object member key. Must not be {@code null}.
313         * @param def The default value to return if the key is not present or
314         *            the value is {@code null}.
315         *
316         * @return The member value.
317         *
318         * @throws ParseException If the value is not of the expected type.
319         */
320        public static float getFloat(final JSONObject o, final String key, final float def)
321                throws ParseException {
322                
323                if (o.get(key) != null) {
324                        return getFloat(o, key);
325                }
326                
327                return def;
328        }
329        
330        
331        /**
332         * Gets a number member of a JSON object as {@code double}.
333         *
334         * @param o   The JSON object. Must not be {@code null}.
335         * @param key The JSON object member key. Must not be {@code null}.
336         *
337         * @return The member value.
338         *
339         * @throws ParseException If the value is missing, {@code null} or not
340         *                        of the expected type.
341         */
342        public static double getDouble(final JSONObject o, final String key)
343                throws ParseException {
344                
345                return getGeneric(o, key, Number.class).doubleValue();
346        }
347        
348        
349        /**
350         * Gets a number member of a JSON object as {@code double}.
351         *
352         * @param o   The JSON object. Must not be {@code null}.
353         * @param key The JSON object member key. Must not be {@code null}.
354         * @param def The default value to return if the key is not present or
355         *            the value is {@code null}.
356         *
357         * @return The member value.
358         *
359         * @throws ParseException If the value is not of the expected type.
360         */
361        public static double getDouble(final JSONObject o, final String key, final double def)
362                throws ParseException {
363                
364                if (o.get(key) != null) {
365                        return getDouble(o, key);
366                }
367                
368                return def;
369        }
370
371
372        /**
373         * Gets a number member of a JSON object as {@code java.lang.Number}.
374         *
375         * @param o   The JSON object. Must not be {@code null}.
376         * @param key The JSON object member key. Must not be {@code null}.
377         *
378         * @return The member value.
379         *
380         * @throws ParseException If the value is missing, {@code null} or not
381         *                        of the expected type.
382         */
383        public static Number getNumber(final JSONObject o, final String key)
384                throws ParseException {
385
386                return getGeneric(o, key, Number.class);
387        }
388
389
390        /**
391         * Gets a number member of a JSON object as {@code java.lang.Number}.
392         *
393         * @param o   The JSON object. Must not be {@code null}.
394         * @param key The JSON object member key. Must not be {@code null}.
395         * @param def The default value to return if the key is not present or
396         *            the value is {@code null}. May be {@code null}.
397         *
398         * @return The member value.
399         *
400         * @throws ParseException If the value is not of the expected type.
401         */
402        public static Number getNumber(final JSONObject o, final String key, final Number def)
403                throws ParseException {
404
405                if (o.get(key) != null) {
406                        return getNumber(o, key);
407                }
408                
409                return def;
410        }
411        
412        
413        /**
414         * Gets a string member of a JSON object.
415         *
416         * @param o   The JSON object. Must not be {@code null}.
417         * @param key The JSON object member key. Must not be {@code null}.
418         *
419         * @return The member value.
420         *
421         * @throws ParseException If the value is missing, {@code null} or not
422         *                        of the expected type.
423         */
424        public static String getString(final JSONObject o, final String key)
425                throws ParseException {
426                
427                return getGeneric(o, key, String.class);
428        }
429        
430        
431        /**
432         * Gets a string member of a JSON object.
433         *
434         * @param o   The JSON object. Must not be {@code null}.
435         * @param key The JSON object member key. Must not be {@code null}.
436         * @param def The default value to return if the key is not present or
437         *            the value is {@code null}. May be {@code null}.
438         *
439         * @return The member value.
440         *
441         * @throws ParseException If the value is not of the expected type.
442         */
443        public static String getString(final JSONObject o, final String key, final String def)
444                throws ParseException {
445                
446                if (o.get(key) != null) {
447                        return getString(o, key);
448                }
449                
450                return def;
451        }
452
453
454        /**
455         * Gets a string member of a JSON object.
456         *
457         * @param o   The JSON object. Must not be {@code null}.
458         * @param key The JSON object member key. Must not be {@code null}.
459         *
460         * @return The member value.
461         *
462         * @throws ParseException If the value is missing, {@code null}, not of
463         *                        the expected type, empty or blank.
464         */
465        public static String getNonBlankString(final JSONObject o, final String key)
466                throws ParseException {
467
468                String value = getString(o, key);
469                if (StringUtils.isBlank(value)) {
470                        throw new ParseException("Empty or blank JSON object member with key " + key);
471                }
472                return value;
473        }
474
475
476        /**
477         * Gets a string member of a JSON object as an enumerated object.
478         *
479         * @param o         The JSON object. Must not be {@code null}.
480         * @param key       The JSON object member key. Must not be
481         *                  {@code null}.
482         * @param enumClass The enumeration class. Must not be {@code null}.
483         *
484         * @return The member value.
485         *
486         * @throws ParseException If the value is missing, {@code null} or not
487         *                        of the expected type.
488         */
489        public static <T extends Enum<T>> T getEnum(final JSONObject o, 
490                                                    final String key,
491                                                    final Class<T> enumClass)
492                throws ParseException {
493
494                String value = getString(o, key);
495
496                for (T en: enumClass.getEnumConstants()) {
497                               
498                        if (en.toString().equalsIgnoreCase(value))
499                                return en;
500                }
501
502                throw new ParseException("Unexpected value of JSON object member with key " + key + "");
503        }
504
505
506        /**
507         * Gets a string member of a JSON object as an enumerated object.
508         *
509         * @param o         The JSON object. Must not be {@code null}.
510         * @param key       The JSON object member key. Must not be
511         *                  {@code null}.
512         * @param enumClass The enumeration class. Must not be {@code null}.
513         * @param def       The default value to return if the key is not
514         *                  present or the value is {@code null}. May be
515         *                  {@code null}.
516         *
517         * @return The member value.
518         *
519         * @throws ParseException If the value is not of the expected type.
520         */
521        public static <T extends Enum<T>> T getEnum(final JSONObject o,
522                                                    final String key,
523                                                    final Class<T> enumClass,
524                                                    final T def)
525                throws ParseException {
526
527                if (o.get(key) != null) {
528                        return getEnum(o, key, enumClass);
529                }
530                
531                return def;
532        }
533
534
535        /**
536         * Gets a string member of a JSON object as {@code java.net.URI}.
537         *
538         * @param o   The JSON object. Must not be {@code null}.
539         * @param key The JSON object member key. Must not be {@code null}.
540         *
541         * @return The member value.
542         *
543         * @throws ParseException If the value is missing, {@code null} or not
544         *                        of the expected type.
545         */
546        public static URI getURI(final JSONObject o, final String key)
547                throws ParseException {
548
549                try {
550                        return new URI(getGeneric(o, key, String.class));
551
552                } catch (URISyntaxException e) {
553
554                        throw new ParseException(e.getMessage(), e);
555                }
556        }
557
558
559        /**
560         * Gets a string member of a JSON object as {@code java.net.URI}.
561         *
562         * @param o   The JSON object. Must not be {@code null}.
563         * @param key The JSON object member key. Must not be {@code null}.
564         * @param def The default value to return if the key is not present or
565         *            the value is {@code null}. May be {@code null}.
566         *
567         * @return The member value.
568         *
569         * @throws ParseException If the value is not of the expected type.
570         */
571        public static URI getURI(final JSONObject o, final String key, final URI def)
572                throws ParseException {
573
574                if (o.get(key) != null) {
575                        return getURI(o, key);
576                }
577                
578                return def;
579        }
580        
581        
582        /**
583         * Gets a string member of a JSON object as {@code java.net.URL}.
584         *
585         * @param o   The JSON object. Must not be {@code null}.
586         * @param key The JSON object member key. Must not be {@code null}.
587         *
588         * @return The member value.
589         *
590         * @throws ParseException If the value is missing, {@code null} or not
591         *                        of the expected type.
592         */
593        public static URL getURL(final JSONObject o, final String key)
594                throws ParseException {
595                
596                try {
597                        return new URL(getGeneric(o, key, String.class));
598                        
599                } catch (MalformedURLException e) {
600                
601                        throw new ParseException(e.getMessage(), e);
602                }
603        }
604        
605        
606        /**
607         * Gets a string member of a JSON object as {@code java.net.URL}.
608         *
609         * @param o   The JSON object. Must not be {@code null}.
610         * @param key The JSON object member key. Must not be {@code null}.
611         * @param def The default value to return if the key is not present or
612         *            the value is {@code null}. May be {@code null}.
613         *
614         * @return The member value.
615         *
616         * @throws ParseException If the value is not of the expected type.
617         */
618        public static URL getURL(final JSONObject o, final String key, final URL def)
619                throws ParseException {
620                
621                if (o.get(key) != null) {
622                        return getURL(o, key);
623                }
624                
625                return def;
626        }
627        
628        
629        /**
630         * Gets a JSON array member of a JSON object.
631         *
632         * @param o   The JSON object. Must not be {@code null}.
633         * @param key The JSON object member key. Must not be {@code null}.
634         *
635         * @return The member value.
636         *
637         * @throws ParseException If the value is missing, {@code null} or not
638         *                        of the expected type.
639         */
640        public static JSONArray getJSONArray(final JSONObject o, final String key)
641                throws ParseException {
642                
643                List<?> list = getGeneric(o, key, List.class);
644                JSONArray jsonArray = new JSONArray();
645                jsonArray.addAll(list);
646                return jsonArray;
647        }
648        
649        
650        /**
651         * Gets a JSON array member of a JSON object.
652         *
653         * @param o   The JSON object. Must not be {@code null}.
654         * @param key The JSON object member key. Must not be {@code null}.
655         * @param def The default value to return if the key is not present or
656         *            the value is {@code null}. May be {@code null}.
657         *
658         * @return The member value.
659         *
660         * @throws ParseException If the value is not of the expected type.
661         */
662        public static JSONArray getJSONArray(final JSONObject o, final String key, final JSONArray def)
663                throws ParseException {
664                
665                if (o.get(key) != null) {
666                        return getJSONArray(o, key);
667                }
668                
669                return def;
670        }
671
672
673        /**
674         * Gets a list member of a JSON object.
675         *
676         * @param o   The JSON object. Must not be {@code null}.
677         * @param key The JSON object member key. Must not be {@code null}.
678         *
679         * @return The member value.
680         *
681         * @throws ParseException If the value is missing, {@code null} or not
682         *                        of the expected type.
683         */
684        @SuppressWarnings("unchecked")
685        public static List<Object> getList(final JSONObject o, final String key)
686                throws ParseException {
687                
688                return getGeneric(o, key, List.class);
689        }
690
691
692        /**
693         * Gets a list member of a JSON object.
694         *
695         * @param o   The JSON object. Must not be {@code null}.
696         * @param key The JSON object member key. Must not be {@code null}.
697         * @param def The default value to return if the key is not present or
698         *            the value is {@code null}. May be {@code null}.
699         *
700         * @return The member value.
701         *
702         * @throws ParseException If the value is not of the expected type.
703         */
704        public static List<Object> getList(final JSONObject o, final String key, final List<Object> def)
705                throws ParseException {
706                
707                if (o.get(key) != null) {
708                        return getList(o, key);
709                }
710                
711                return def;
712        }
713
714
715        /**
716         * Gets a string array member of a JSON object.
717         *
718         * @param o   The JSON object. Must not be {@code null}.
719         * @param key The JSON object member key. Must not be {@code null}.
720         *
721         * @return The member value.
722         *
723         * @throws ParseException If the value is missing, {@code null} or not
724         *                        of the expected type.
725         */
726        public static String[] getStringArray(final JSONObject o, final String key)
727                throws ParseException {
728
729                List<Object> list = getList(o, key);
730
731                try {
732                        return list.toArray(new String[0]);
733
734                } catch (ArrayStoreException e) {
735
736                        throw new ParseException("JSON object member with key " + key + " is not an array of strings");
737                }
738        }
739
740
741        /**
742         * Gets a string array member of a JSON object.
743         *
744         * @param o   The JSON object. Must not be {@code null}.
745         * @param key The JSON object member key. Must not be {@code null}.
746         * @param def The default value to return if the key is not present or
747         *            the value is {@code null}. May be {@code null}.
748         *
749         * @return The member value.
750         *
751         * @throws ParseException If the value is not of the expected type.
752         */
753        public static String[] getStringArray(final JSONObject o, final String key, final String[] def)
754                throws ParseException {
755
756                if (o.get(key) != null) {
757                        return getStringArray(o, key);
758                }
759                
760                return def;
761        }
762
763
764        /**
765         * Gets a string list member of a JSON object.
766         *
767         * @param o   The JSON object. Must not be {@code null}.
768         * @param key The JSON object member key. Must not be {@code null}.
769         *
770         * @return The member value.
771         *
772         * @throws ParseException If the value is missing, {@code null} or not
773         *                        of the expected type.
774         */
775        public static List<String> getStringList(final JSONObject o, final String key)
776                throws ParseException {
777
778                return Arrays.asList(getStringArray(o, key));
779        }
780
781
782        /**
783         * Gets a string list member of a JSON object.
784         *
785         * @param o   The JSON object. Must not be {@code null}.
786         * @param key The JSON object member key. Must not be {@code null}.
787         * @param def The default value to return if the key is not present or
788         *            the value is {@code null}. May be {@code null}.
789         *
790         * @return The member value.
791         *
792         * @throws ParseException If the value is not of the expected type.
793         */
794        public static List<String> getStringList(final JSONObject o, final String key, final List<String> def)
795                throws ParseException {
796
797                if (o.get(key) != null) {
798                        return getStringList(o, key);
799                }
800                
801                return def;
802        }
803
804
805        /**
806         * Gets a string array member of a JSON object as a string set.
807         *
808         * @param o   The JSON object. Must not be {@code null}.
809         * @param key The JSON object member key. Must not be {@code null}.
810         *
811         * @return The member value.
812         *
813         * @throws ParseException If the value is missing, {@code null} or not
814         *                        of the expected type.
815         */
816        public static Set<String> getStringSet(final JSONObject o, final String key)
817                throws ParseException {
818
819                List<Object> list = getList(o, key);
820
821                Set<String> set = new HashSet<>();
822
823                for (Object item: list) {
824
825                        try {
826                                set.add((String)item);
827
828                        } catch (Exception e) {
829
830                                throw new ParseException("JSON object member with key " + key + " is not an array of strings");
831                        }
832
833                }
834
835                return set;
836        }
837
838
839        /**
840         * Gets a string array member of a JSON object as a string set.
841         *
842         * @param o   The JSON object. Must not be {@code null}.
843         * @param key The JSON object member key. Must not be {@code null}.
844         * @param def The default value to return if the key is not present or
845         *            the value is {@code null}. May be {@code null}.
846         *
847         * @return The member value.
848         *
849         * @throws ParseException If the value is not of the expected type.
850         */
851        public static Set<String> getStringSet(final JSONObject o, final String key, final Set<String> def)
852                throws ParseException {
853
854                if (o.get(key) != null) {
855                        return getStringSet(o, key);
856                }
857                
858                return def;
859        }
860        
861        
862        /**
863         * Gets a JSON object member of a JSON object.
864         *
865         * @param o   The JSON object. Must not be {@code null}.
866         * @param key The JSON object member key. Must not be {@code null}.
867         *
868         * @return The member value.
869         *
870         * @throws ParseException If the value is missing, {@code null} or not
871         *                        of the expected type.
872         */
873        public static JSONObject getJSONObject(final JSONObject o, final String key)
874                throws ParseException {
875                
876                @SuppressWarnings("unchecked")
877                Map<String, ?> mapObject = getGeneric(o, key, Map.class);
878                return new JSONObject(mapObject);
879        }
880        
881        
882        /**
883         * Gets a JSON object member of a JSON object.
884         *
885         * @param o   The JSON object. Must not be {@code null}.
886         * @param key The JSON object member key. Must not be {@code null}.
887         * @param def The default value to return if the key is not present or
888         *            the value is {@code null}. May be {@code null}.
889         *
890         * @return The member value.
891         *
892         * @throws ParseException If the value is not of the expected type.
893         */
894        public static JSONObject getJSONObject(final JSONObject o, final String key, final JSONObject def)
895                throws ParseException {
896                
897                if (o.get(key) != null) {
898                        return getJSONObject(o, key);
899                }
900                
901                return def;
902        }
903        
904        
905        /**
906         * Returns the JSON object representation of the specified JWT claims
907         * set.
908         *
909         * @param jwtClaimsSet The JWT claims set, {@code null} if not
910         *                     specified.
911         *
912         * @return The JSON object, {@code null} if not specified.
913         */
914        public static JSONObject toJSONObject(final JWTClaimsSet jwtClaimsSet) {
915                
916                if (jwtClaimsSet == null) {
917                        return null;
918                }
919                
920                if (jwtClaimsSet.getClaims().isEmpty()) {
921                        return new JSONObject();
922                }
923                
924                // Serialise and parse is the safest method
925                final String json = jwtClaimsSet.toString();
926                
927                try {
928                        return parse(json);
929                } catch (ParseException e) {
930                        // Should never happen
931                        return null;
932                }
933        }
934        
935        
936        /**
937         * Returns the JSON object representation of the specified JWK set.
938         *
939         * @param jwkSet The JWK set, {@code null} if not specified.
940         *
941         * @return The JSON object, {@code null} if not specified.
942         */
943        public static JSONObject toJSONObject(final JWKSet jwkSet) {
944                
945                if (jwkSet == null) {
946                        return null;
947                }
948                
949                // Serialise and parse is the safest method
950                final String json = jwkSet.toString(false);
951                
952                try {
953                        return parse(json);
954                } catch (ParseException e) {
955                        // Should never happen
956                        return null;
957                }
958        }
959        
960
961        /**
962         * Prevents public instantiation.
963         */
964        private JSONObjectUtils() {}
965}
966