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}