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.jwt.JWTClaimsSet;
031import com.nimbusds.oauth2.sdk.ParseException;
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. Must
140         *              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 as an enumerated object.
456         *
457         * @param o         The JSON object. Must not be {@code null}.
458         * @param key       The JSON object member key. Must not be
459         *                  {@code null}.
460         * @param enumClass The enumeration class. Must not be {@code null}.
461         *
462         * @return The member value.
463         *
464         * @throws ParseException If the value is missing, {@code null} or not
465         *                        of the expected type.
466         */
467        public static <T extends Enum<T>> T getEnum(final JSONObject o, 
468                                                    final String key,
469                                                    final Class<T> enumClass)
470                throws ParseException {
471
472                String value = getString(o, key);
473
474                for (T en: enumClass.getEnumConstants()) {
475                               
476                        if (en.toString().equalsIgnoreCase(value))
477                                return en;
478                }
479
480                throw new ParseException("Unexpected value of JSON object member with key " + key + "");
481        }
482
483
484        /**
485         * Gets a string member of a JSON object as an enumerated object.
486         *
487         * @param o         The JSON object. Must not be {@code null}.
488         * @param key       The JSON object member key. Must not be
489         *                  {@code null}.
490         * @param enumClass The enumeration class. Must not be {@code null}.
491         * @param def       The default value to return if the key is not
492         *                  present or the value is {@code null}. May be
493         *                  {@code null}.
494         *
495         * @return The member value.
496         *
497         * @throws ParseException If the value is not of the expected type.
498         */
499        public static <T extends Enum<T>> T getEnum(final JSONObject o,
500                                                    final String key,
501                                                    final Class<T> enumClass,
502                                                    final T def)
503                throws ParseException {
504
505                if (o.get(key) != null) {
506                        return getEnum(o, key, enumClass);
507                }
508                
509                return def;
510        }
511
512
513        /**
514         * Gets a string member of a JSON object as {@code java.net.URI}.
515         *
516         * @param o   The JSON object. Must not be {@code null}.
517         * @param key The JSON object member key. Must not be {@code null}.
518         *
519         * @return The member value.
520         *
521         * @throws ParseException If the value is missing, {@code null} or not
522         *                        of the expected type.
523         */
524        public static URI getURI(final JSONObject o, final String key)
525                throws ParseException {
526
527                try {
528                        return new URI(getGeneric(o, key, String.class));
529
530                } catch (URISyntaxException e) {
531
532                        throw new ParseException(e.getMessage(), e);
533                }
534        }
535
536
537        /**
538         * Gets a string member of a JSON object as {@code java.net.URI}.
539         *
540         * @param o   The JSON object. Must not be {@code null}.
541         * @param key The JSON object member key. Must not be {@code null}.
542         * @param def The default value to return if the key is not present or
543         *            the value is {@code null}. May be {@code null}.
544         *
545         * @return The member value.
546         *
547         * @throws ParseException If the value is not of the expected type.
548         */
549        public static URI getURI(final JSONObject o, final String key, final URI def)
550                throws ParseException {
551
552                if (o.get(key) != null) {
553                        return getURI(o, key);
554                }
555                
556                return def;
557        }
558        
559        
560        /**
561         * Gets a string member of a JSON object as {@code java.net.URL}.
562         *
563         * @param o   The JSON object. Must not be {@code null}.
564         * @param key The JSON object member key. Must not be {@code null}.
565         *
566         * @return The member value.
567         *
568         * @throws ParseException If the value is missing, {@code null} or not
569         *                        of the expected type.
570         */
571        public static URL getURL(final JSONObject o, final String key)
572                throws ParseException {
573                
574                try {
575                        return new URL(getGeneric(o, key, String.class));
576                        
577                } catch (MalformedURLException e) {
578                
579                        throw new ParseException(e.getMessage(), e);
580                }
581        }
582        
583        
584        /**
585         * Gets a JSON array member of a JSON object.
586         *
587         * @param o   The JSON object. Must not be {@code null}.
588         * @param key The JSON object member key. Must not be {@code null}.
589         *
590         * @return The member value.
591         *
592         * @throws ParseException If the value is missing, {@code null} or not
593         *                        of the expected type.
594         */
595        public static JSONArray getJSONArray(final JSONObject o, final String key)
596                throws ParseException {
597                
598                List<?> list = getGeneric(o, key, List.class);
599                JSONArray jsonArray = new JSONArray();
600                jsonArray.addAll(list);
601                return jsonArray;
602        }
603        
604        
605        /**
606         * Gets a JSON array member of a JSON object.
607         *
608         * @param o   The JSON object. Must not be {@code null}.
609         * @param key The JSON object member key. Must not be {@code null}.
610         * @param def The default value to return if the key is not present or
611         *            the value is {@code null}. May be {@code null}.
612         *
613         * @return The member value.
614         *
615         * @throws ParseException If the value is not of the expected type.
616         */
617        public static JSONArray getJSONArray(final JSONObject o, final String key, final JSONArray def)
618                throws ParseException {
619                
620                if (o.get(key) != null) {
621                        return getJSONArray(o, key);
622                }
623                
624                return def;
625        }
626
627
628        /**
629         * Gets a list member of a JSON object.
630         *
631         * @param o   The JSON object. Must not be {@code null}.
632         * @param key The JSON object member key. Must not be {@code null}.
633         *
634         * @return The member value.
635         *
636         * @throws ParseException If the value is missing, {@code null} or not
637         *                        of the expected type.
638         */
639        @SuppressWarnings("unchecked")
640        public static List<Object> getList(final JSONObject o, final String key)
641                throws ParseException {
642                
643                return getGeneric(o, key, List.class);
644        }
645
646
647        /**
648         * Gets a list member of a JSON object.
649         *
650         * @param o   The JSON object. Must not be {@code null}.
651         * @param key The JSON object member key. Must not be {@code null}.
652         * @param def The default value to return if the key is not present or
653         *            the value is {@code null}. May be {@code null}.
654         *
655         * @return The member value.
656         *
657         * @throws ParseException If the value is not of the expected type.
658         */
659        public static List<Object> getList(final JSONObject o, final String key, final List<Object> def)
660                throws ParseException {
661                
662                if (o.get(key) != null) {
663                        return getList(o, key);
664                }
665                
666                return def;
667        }
668
669
670        /**
671         * Gets a string array member of a JSON object.
672         *
673         * @param o   The JSON object. Must not be {@code null}.
674         * @param key The JSON object member key. Must not be {@code null}.
675         *
676         * @return The member value.
677         *
678         * @throws ParseException If the value is missing, {@code null} or not
679         *                        of the expected type.
680         */
681        public static String[] getStringArray(final JSONObject o, final String key)
682                throws ParseException {
683
684                List<Object> list = getList(o, key);
685
686                try {
687                        return list.toArray(new String[0]);
688
689                } catch (ArrayStoreException e) {
690
691                        throw new ParseException("JSON object member with key " + key + " is not an array of strings");
692                }
693        }
694
695
696        /**
697         * Gets a string array member of a JSON object.
698         *
699         * @param o   The JSON object. Must not be {@code null}.
700         * @param key The JSON object member key. Must not be {@code null}.
701         * @param def The default value to return if the key is not present or
702         *            the value is {@code null}. May be {@code null}.
703         *
704         * @return The member value.
705         *
706         * @throws ParseException If the value is not of the expected type.
707         */
708        public static String[] getStringArray(final JSONObject o, final String key, final String[] def)
709                throws ParseException {
710
711                if (o.get(key) != null) {
712                        return getStringArray(o, key);
713                }
714                
715                return def;
716        }
717
718
719        /**
720         * Gets a string list member of a JSON object.
721         *
722         * @param o   The JSON object. Must not be {@code null}.
723         * @param key The JSON object member key. Must not be {@code null}.
724         *
725         * @return The member value.
726         *
727         * @throws ParseException If the value is missing, {@code null} or not
728         *                        of the expected type.
729         */
730        public static List<String> getStringList(final JSONObject o, final String key)
731                throws ParseException {
732
733                return Arrays.asList(getStringArray(o, key));
734        }
735
736
737        /**
738         * Gets a string list member of a JSON object.
739         *
740         * @param o   The JSON object. Must not be {@code null}.
741         * @param key The JSON object member key. Must not be {@code null}.
742         * @param def The default value to return if the key is not present or
743         *            the value is {@code null}. May be {@code null}.
744         *
745         * @return The member value.
746         *
747         * @throws ParseException If the value is not of the expected type.
748         */
749        public static List<String> getStringList(final JSONObject o, final String key, final List<String> def)
750                throws ParseException {
751
752                if (o.get(key) != null) {
753                        return getStringList(o, key);
754                }
755                
756                return def;
757        }
758
759
760        /**
761         * Gets a string array member of a JSON object as a string set.
762         *
763         * @param o   The JSON object. Must not be {@code null}.
764         * @param key The JSON object member key. Must not be {@code null}.
765         *
766         * @return The member value.
767         *
768         * @throws ParseException If the value is missing, {@code null} or not
769         *                        of the expected type.
770         */
771        public static Set<String> getStringSet(final JSONObject o, final String key)
772                throws ParseException {
773
774                List<Object> list = getList(o, key);
775
776                Set<String> set = new HashSet<>();
777
778                for (Object item: list) {
779
780                        try {
781                                set.add((String)item);
782
783                        } catch (Exception e) {
784
785                                throw new ParseException("JSON object member with key " + key + " is not an array of strings");
786                        }
787
788                }
789
790                return set;
791        }
792
793
794        /**
795         * Gets a string array member of a JSON object as a string set.
796         *
797         * @param o   The JSON object. Must not be {@code null}.
798         * @param key The JSON object member key. Must not be {@code null}.
799         * @param def The default value to return if the key is not present or
800         *            the value is {@code null}. May be {@code null}.
801         *
802         * @return The member value.
803         *
804         * @throws ParseException If the value is not of the expected type.
805         */
806        public static Set<String> getStringSet(final JSONObject o, final String key, final Set<String> def)
807                throws ParseException {
808
809                if (o.get(key) != null) {
810                        return getStringSet(o, key);
811                }
812                
813                return def;
814        }
815        
816        
817        /**
818         * Gets a JSON object member of a JSON object.
819         *
820         * @param o   The JSON object. Must not be {@code null}.
821         * @param key The JSON object member key. Must not be {@code null}.
822         *
823         * @return The member value.
824         *
825         * @throws ParseException If the value is missing, {@code null} or not
826         *                        of the expected type.
827         */
828        public static JSONObject getJSONObject(final JSONObject o, final String key)
829                throws ParseException {
830                
831                @SuppressWarnings("unchecked")
832                Map<String, ?> mapObject = getGeneric(o, key, Map.class);
833                return new JSONObject(mapObject);
834        }
835        
836        
837        /**
838         * Gets a JSON object member of a JSON object.
839         *
840         * @param o   The JSON object. Must not be {@code null}.
841         * @param key The JSON object member key. Must not be {@code null}.
842         * @param def The default value to return if the key is not present or
843         *            the value is {@code null}. May be {@code null}.
844         *
845         * @return The member value.
846         *
847         * @throws ParseException If the value is not of the expected type.
848         */
849        public static JSONObject getJSONObject(final JSONObject o, final String key, final JSONObject def)
850                throws ParseException {
851                
852                if (o.get(key) != null) {
853                        return getJSONObject(o, key);
854                }
855                
856                return def;
857        }
858        
859        
860        /**
861         * Returns the JSON object representation of the specified JWT claims
862         * set.
863         *
864         * @param jwtClaimsSet The JWT claims set, {@code null} if not
865         *                     specified.
866         *
867         * @return The JSON object, {@code null} if not specified.
868         */
869        public static JSONObject toJSONObject(final JWTClaimsSet jwtClaimsSet) {
870                
871                if (jwtClaimsSet == null) {
872                        return null;
873                }
874                
875                if (jwtClaimsSet.getClaims().isEmpty()) {
876                        return new JSONObject();
877                }
878                
879                // Serialise and parse is the safest method
880                final String json = jwtClaimsSet.toString();
881                
882                try {
883                        return parse(json);
884                } catch (ParseException e) {
885                        // Should never happen
886                        return null;
887                }
888        }
889        
890
891        /**
892         * Prevents public instantiation.
893         */
894        private JSONObjectUtils() {}
895}
896