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.util.LinkedList;
022import java.util.List;
023
024import com.nimbusds.oauth2.sdk.ParseException;
025
026import net.minidev.json.parser.JSONParser;
027import net.minidev.json.writer.JsonReader;
028
029
030/**
031 * JSON helper methods.
032 */
033public final class JSONUtils {
034
035
036        /**
037         * Parses a JSON value.
038         *
039         * @param s The JSON string to parse. Must not be {@code null}.
040         *
041         * @return The JSON value.
042         *
043         * @throws ParseException If the string cannot be parsed to a JSON
044         *                        value.
045         */
046        public static Object parseJSON(final String s)
047                throws ParseException {
048
049                try {
050                        return new JSONParser(JSONParser.USE_HI_PRECISION_FLOAT | JSONParser.ACCEPT_TAILLING_SPACE).parse(s);
051
052                } catch (net.minidev.json.parser.ParseException e) {
053
054                        throw new ParseException("Invalid JSON: " + e.getMessage(), e);
055                }
056        }
057
058
059        /**
060         * Parses a JSON value while keeping the order of JSON object members.
061         *
062         * @param s The JSON string to parse. Must not be {@code null}.
063         *
064         * @return The JSON value.
065         *
066         * @throws ParseException If the string cannot be parsed to a JSON
067         *                        value.
068         */
069        public static Object parseJSONKeepingOrder(final String s)
070                throws ParseException {
071
072                try {
073                        return new JSONParser(JSONParser.USE_HI_PRECISION_FLOAT | JSONParser.ACCEPT_TAILLING_SPACE).parse(s, new JsonReader().DEFAULT_ORDERED);
074
075                } catch (net.minidev.json.parser.ParseException e) {
076
077                        throw new ParseException("Invalid JSON: " + e.getMessage(), e);
078                }
079        }
080        
081        
082        /**
083         * Casts an object.
084         *
085         * @param o     The object. Must not be {@code null}.
086         * @param clazz The expected class of the object. Must not be
087         *              {@code null}.
088         *
089         * @return The cast object.
090         *
091         * @throws ParseException If the object is not of the expected type.
092         */
093        @SuppressWarnings("unchecked")
094        public static <T> T to(final Object o, final Class<T> clazz)
095                throws ParseException {
096                
097                if (! clazz.isAssignableFrom(o.getClass()))
098                        throw new ParseException("Unexpected type: " + o.getClass());
099                
100                return (T)o;
101        }
102        
103        
104        /**
105         * Casts an object to a boolean.
106         *
107         * @param o The object. Must not be {@code null}.
108         *
109         * @return The boolean value.
110         *
111         * @throws ParseException If the object is not of the expected type.
112         */
113        public static boolean toBoolean(final Object o)
114                throws ParseException {
115                
116                return to(o, Boolean.class);
117        }
118        
119        
120        /**
121         * Casts an object to a number.
122         *
123         * @param o The object. Must not be {@code null}.
124         *
125         * @return The number.
126         *
127         * @throws ParseException If the object is not of the expected type.
128         */
129        public static Number toNumber(final Object o)
130                throws ParseException {
131                
132                return to(o, Number.class);
133        }
134        
135        
136        /**
137         * Casts an object to a string.
138         *
139         * @param o The object. Must not be {@code null}.
140         *
141         * @return The string.
142         *
143         * @throws ParseException If the object is not of the expected type.
144         */
145        public static String toString(final Object o)
146                throws ParseException {
147                
148                return to(o, String.class);
149        }
150        
151        
152        /**
153         * Casts an object to a list.
154         *
155         * @param o The object. Must not be {@code null}.
156         *
157         * @return The list.
158         *
159         * @throws ParseException If the object is not of the expected type.
160         */
161        public static List<?> toList(final Object o)
162                throws ParseException {
163                
164                return to(o, List.class);
165        }
166        
167        
168        /**
169         * Casts an object to a list then returns a string list copy of it
170         * casting each item to a string.
171         *
172         * @param o The object. Must not be {@code null}.
173         *
174         * @return The string list.
175         *
176         * @throws ParseException If the object is not of the expected type.
177         */
178        public static List<String> toStringList(final Object o)
179                throws ParseException {
180                
181                List<String> stringList = new LinkedList<>();
182                try {
183                        for (Object item: toList(o)) {
184                                stringList.add((String)item);
185                        }
186                } catch (ClassCastException e) {
187                        throw new ParseException("Item not a string");
188                }
189                return stringList;
190        }
191        
192        
193        /**
194         * Prevents instantiation.
195         */
196        private JSONUtils() {}
197}