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( 051 JSONParser.USE_HI_PRECISION_FLOAT | 052 JSONParser.ACCEPT_TAILLING_SPACE | 053 JSONParser.LIMIT_JSON_DEPTH 054 ).parse(s); 055 } catch (net.minidev.json.parser.ParseException e) { 056 throw new ParseException("Invalid JSON", e); 057 } catch (NullPointerException e) { 058 throw new ParseException("The JSON string must not be null", e); 059 } catch (Exception e) { 060 throw new ParseException("Unexpected exception: " + e.getMessage(), e); 061 } catch (Error e) { 062 // Guard against unexpected java.lang.Error instances 063 throw new ParseException("Unexpected error: " + e.getMessage(), e); 064 } 065 } 066 067 068 /** 069 * Parses a JSON value while keeping the order of JSON object members. 070 * 071 * @param s The JSON string to parse. Must not be {@code null}. 072 * 073 * @return The JSON value. 074 * 075 * @throws ParseException If the string cannot be parsed to a JSON 076 * value. 077 */ 078 public static Object parseJSONKeepingOrder(final String s) 079 throws ParseException { 080 081 try { 082 return new JSONParser( 083 JSONParser.USE_HI_PRECISION_FLOAT | 084 JSONParser.ACCEPT_TAILLING_SPACE | 085 JSONParser.LIMIT_JSON_DEPTH 086 ).parse(s, new JsonReader().DEFAULT_ORDERED); 087 088 } catch (net.minidev.json.parser.ParseException e) { 089 throw new ParseException("Invalid JSON", e); 090 } catch (NullPointerException e) { 091 throw new ParseException("The JSON string must not be null", e); 092 } catch (Exception e) { 093 throw new ParseException("Unexpected exception: " + e.getMessage(), e); 094 } catch (Error e) { 095 // Guard against unexpected java.lang.Error instances 096 throw new ParseException("Unexpected error: " + e.getMessage(), e); 097 } 098 } 099 100 101 /** 102 * Casts an object. 103 * 104 * @param o The object. Must not be {@code null}. 105 * @param clazz The expected class of the object. Must not be 106 * {@code null}. 107 * 108 * @return The cast object. 109 * 110 * @throws ParseException If the object is not of the expected type. 111 */ 112 @SuppressWarnings("unchecked") 113 public static <T> T to(final Object o, final Class<T> clazz) 114 throws ParseException { 115 116 if (! clazz.isAssignableFrom(o.getClass())) 117 throw new ParseException("Unexpected type: " + o.getClass()); 118 119 return (T)o; 120 } 121 122 123 /** 124 * Casts an object to a boolean. 125 * 126 * @param o The object. Must not be {@code null}. 127 * 128 * @return The boolean value. 129 * 130 * @throws ParseException If the object is not of the expected type. 131 */ 132 public static boolean toBoolean(final Object o) 133 throws ParseException { 134 135 return to(o, Boolean.class); 136 } 137 138 139 /** 140 * Casts an object to a number. 141 * 142 * @param o The object. Must not be {@code null}. 143 * 144 * @return The number. 145 * 146 * @throws ParseException If the object is not of the expected type. 147 */ 148 public static Number toNumber(final Object o) 149 throws ParseException { 150 151 return to(o, Number.class); 152 } 153 154 155 /** 156 * Casts an object to a string. 157 * 158 * @param o The object. Must not be {@code null}. 159 * 160 * @return The string. 161 * 162 * @throws ParseException If the object is not of the expected type. 163 */ 164 public static String toString(final Object o) 165 throws ParseException { 166 167 return to(o, String.class); 168 } 169 170 171 /** 172 * Casts an object to a list. 173 * 174 * @param o The object. Must not be {@code null}. 175 * 176 * @return The list. 177 * 178 * @throws ParseException If the object is not of the expected type. 179 */ 180 public static List<?> toList(final Object o) 181 throws ParseException { 182 183 return to(o, List.class); 184 } 185 186 187 /** 188 * Casts an object to a list then returns a string list copy of it 189 * casting each item to a string. 190 * 191 * @param o The object. Must not be {@code null}. 192 * 193 * @return The string list. 194 * 195 * @throws ParseException If the object is not of the expected type. 196 */ 197 public static List<String> toStringList(final Object o) 198 throws ParseException { 199 200 List<String> stringList = new LinkedList<>(); 201 try { 202 for (Object item: toList(o)) { 203 stringList.add((String)item); 204 } 205 } catch (ClassCastException e) { 206 throw new ParseException("Item not a string"); 207 } 208 return stringList; 209 } 210 211 212 /** 213 * Prevents instantiation. 214 */ 215 private JSONUtils() {} 216}