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