001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2024, Connect2id Ltd.
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 */
017package com.nimbusds.jose.util;
018
019import com.google.gson.Gson;
020import com.google.gson.GsonBuilder;
021import com.google.gson.Strictness;
022import com.google.gson.ToNumberPolicy;
023import com.google.gson.reflect.TypeToken;
024
025import java.lang.reflect.Type;
026import java.text.ParseException;
027import java.util.ArrayList;
028import java.util.List;
029import java.util.Objects;
030
031
032/**
033 * JSON array helper methods.
034 *
035 * @author Toma Velev
036 * @author Vladimir Dzhuvinov
037 * @version 2024-11-14
038 */
039public class JSONArrayUtils {
040
041
042        /**
043         * The GSon instance for serialisation and parsing.
044         */
045        private static final Gson GSON = new GsonBuilder()
046                .setStrictness(Strictness.STRICT)
047                .serializeNulls()
048                .setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
049                .disableHtmlEscaping()
050                .create();
051
052
053        /**
054         * Parses a JSON array.
055         *
056         * <p>Specific JSON to Java entity mapping (as per JSON Smart):
057         *
058         * <ul>
059         *     <li>JSON true|false map to {@code java.lang.Boolean}.
060         *     <li>JSON numbers map to {@code java.lang.Number}.
061         *         <ul>
062         *             <li>JSON integer numbers map to {@code long}.
063         *             <li>JSON fraction numbers map to {@code double}.
064         *         </ul>
065         *     <li>JSON strings map to {@code java.lang.String}.
066         *     <li>JSON arrays map to {@code java.util.List<Object>}.
067         *     <li>JSON objects map to {@code java.util.Map<String,Object>}.
068         * </ul>
069         *
070         * @param s The JSON array string to parse. Must not be {@code null}.
071         *
072         * @return The JSON object.
073         *
074         * @throws ParseException If the string cannot be parsed to a valid JSON
075         *                        object.
076         */
077        public static List<Object> parse(final String s)
078                throws ParseException {
079
080                if (s == null) {
081                        throw new ParseException("The JSON array string must not be null", 0);
082                }
083
084                if (s.trim().isEmpty()) {
085                        throw new ParseException("Invalid JSON array", 0);
086                }
087
088                Type listType = TypeToken.getParameterized(List.class, Object.class).getType();
089
090                try {
091                        return GSON.fromJson(s, listType);
092                } catch (Exception e) {
093                        throw new ParseException("Invalid JSON array", 0);
094                } catch (StackOverflowError e) {
095                        throw new ParseException("Excessive JSON object and / or array nesting", 0);
096                }
097        }
098
099
100        /**
101         * Serialises the specified list to a JSON array using the entity
102         * mapping specified in {@link #parse(String)}.
103         *
104         * @param jsonArray The JSON array. Must not be {@code null}.
105         *
106         * @return The JSON array as string.
107         */
108        public static String toJSONString(final List<?> jsonArray) {
109                return GSON.toJson(Objects.requireNonNull(jsonArray));
110        }
111
112
113        /**
114         * Creates a new JSON array.
115         *
116         * @return The new empty JSON array.
117         */
118        public static List<Object> newJSONArray() {
119                return new ArrayList<>();
120        }
121        
122        
123        /**
124         * Prevents public instantiation.
125         */
126        private JSONArrayUtils() { }
127}