001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.ametys.core.util; 018 019import java.io.IOException; 020import java.io.InputStream; 021import java.io.InputStreamReader; 022import java.io.OutputStream; 023import java.io.StringReader; 024import java.io.StringWriter; 025import java.nio.charset.Charset; 026import java.util.ArrayList; 027import java.util.LinkedHashMap; 028import java.util.List; 029import java.util.Map; 030 031import org.apache.avalon.framework.activity.Initializable; 032import org.apache.avalon.framework.component.Component; 033import org.apache.avalon.framework.service.ServiceException; 034import org.apache.avalon.framework.service.ServiceManager; 035import org.apache.avalon.framework.service.Serviceable; 036import org.apache.avalon.framework.thread.ThreadSafe; 037import org.apache.commons.lang3.StringUtils; 038 039import org.ametys.plugins.core.ui.help.HelpSerializer; 040 041import com.fasterxml.jackson.core.JsonEncoding; 042import com.fasterxml.jackson.core.JsonFactory; 043import com.fasterxml.jackson.core.JsonGenerator; 044import com.fasterxml.jackson.core.JsonParser; 045import com.fasterxml.jackson.core.Version; 046import com.fasterxml.jackson.databind.ObjectMapper; 047import com.fasterxml.jackson.databind.module.SimpleModule; 048 049/** 050 * JSON helper 051 */ 052public class JSONUtils implements Component, ThreadSafe, Serviceable, Initializable 053{ 054 /** The avalon role */ 055 public static final String ROLE = JSONUtils.class.getName(); 056 057 private JsonFactory _jsonFactory = new JsonFactory(); 058 private ObjectMapper _objectMapper = new ObjectMapper(); 059 060 private I18nizableSerializer _i18nizableSerializer; 061 private HelpSerializer _helpSerializer; 062 private ZonedDateTimeSerializer _zoneDateTimeSerializer; 063 private LocalDateSerializer _localDateSerializer; 064 065 @Override 066 public void service(ServiceManager manager) throws ServiceException 067 { 068 _i18nizableSerializer = (I18nizableSerializer) manager.lookup(I18nizableSerializer.ROLE); 069 _zoneDateTimeSerializer = (ZonedDateTimeSerializer) manager.lookup(ZonedDateTimeSerializer.ROLE); 070 _localDateSerializer = (LocalDateSerializer) manager.lookup(LocalDateSerializer.ROLE); 071 _helpSerializer = (HelpSerializer) manager.lookup(HelpSerializer.ROLE); 072 } 073 074 @Override 075 public void initialize() throws Exception 076 { 077 // Register new serializer for I18nizableText 078 SimpleModule i18nModule = new SimpleModule("AmetysI18nModule", new Version(1, 0, 0, null, null, null)); 079 i18nModule.addSerializer(_i18nizableSerializer); 080 _objectMapper.registerModule(i18nModule); 081 082 // Register new serializer for help url 083 SimpleModule helpModule = new SimpleModule("AmetysHelpModule", new Version(1, 0, 0, null, null, null)); 084 helpModule.addSerializer(_helpSerializer); 085 _objectMapper.registerModule(helpModule); 086 087 // Register new serializer for ZonedDateTime 088 SimpleModule zoneDateTimeModule = new SimpleModule("AmetysZonedDateTimeModule", new Version(1, 0, 0, null, null, null)); 089 zoneDateTimeModule.addSerializer(_zoneDateTimeSerializer); 090 _objectMapper.registerModule(zoneDateTimeModule); 091 092 // Register new serializer for LocalDate 093 SimpleModule localDateModule = new SimpleModule("AmetysLocalDateModule", new Version(1, 0, 0, null, null, null)); 094 localDateModule.addSerializer(_localDateSerializer); 095 _objectMapper.registerModule(localDateModule); 096 } 097 098 /** 099 * Parse a JSON string to a {@link Map} object 100 * @param jsonString the string to parse 101 * @return object the infos as a Map. 102 */ 103 public Map<String, Object> convertJsonToMap (String jsonString) 104 { 105 try 106 { 107 if (StringUtils.isNotBlank(jsonString)) 108 { 109 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 110 Map<String, Object> map = _objectMapper.readValue(jParser, LinkedHashMap.class); 111 return map; 112 } 113 else 114 { 115 return new LinkedHashMap<>(); // We should not return a Collections.emptyMap() here, since we need to return a modifiable map that is always of the same type 116 } 117 } 118 catch (Exception e) 119 { 120 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a Map.", e); 121 } 122 } 123 124 /** 125 * Parse a JSON input stream to a {@link Map} object 126 * @param jsonInput the input stream to parse 127 * @param charset the charset of the stream 128 * @return object the infos as a Map. 129 */ 130 public Map<String, Object> convertJsonToMap(InputStream jsonInput, Charset charset) 131 { 132 try (InputStreamReader reader = new InputStreamReader(jsonInput, charset); 133 JsonParser jParser = _jsonFactory.createParser(reader)) 134 { 135 return _objectMapper.readValue(jParser, LinkedHashMap.class); 136 } 137 catch (Exception e) 138 { 139 throw new IllegalArgumentException("The json input can not be parsed as a Map.", e); 140 } 141 } 142 143 /** 144 * Parse a JSON string to a {@link List} object. 145 * @param jsonString the string to parse. 146 * @return the infos as a List. 147 */ 148 public List<Object> convertJsonToList(String jsonString) 149 { 150 try 151 { 152 if (StringUtils.isNotBlank(jsonString)) 153 { 154 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 155 List<Object> list = _objectMapper.readValue(jParser, ArrayList.class); 156 return list; 157 } 158 else 159 { 160 return new ArrayList<>(); 161 } 162 } 163 catch (Exception e) 164 { 165 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a List.", e); 166 } 167 } 168 169 /** 170 * Parse a JSON input stream to a {@link List} object. 171 * @param jsonInput the input stream to parse 172 * @param charset the charset of the stream 173 * @return the infos as a List. 174 */ 175 public List<Object> convertJsonToList(InputStream jsonInput, Charset charset) 176 { 177 try (InputStreamReader reader = new InputStreamReader(jsonInput, charset); 178 JsonParser jParser = _jsonFactory.createParser(reader)) 179 { 180 return _objectMapper.readValue(jParser, ArrayList.class); 181 } 182 catch (Exception e) 183 { 184 throw new IllegalArgumentException("The json input can not be parsed as a Map.", e); 185 } 186 } 187 188 /** 189 * Parse a JSON string to an Object array. 190 * @param jsonString the JSON string to parse. 191 * @return the converted Object array. 192 */ 193 public Object[] convertJsonToArray(String jsonString) 194 { 195 try 196 { 197 if (StringUtils.isNotBlank(jsonString)) 198 { 199 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 200 Object[] array = _objectMapper.readValue(jParser, Object[].class); 201 return array; 202 } 203 else 204 { 205 return new Object[0]; 206 } 207 } 208 catch (Exception e) 209 { 210 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as an array.", e); 211 } 212 } 213 214 /** 215 * Parse a JSON input stream to an {@link Object} array. 216 * @param jsonInput the input stream to parse 217 * @param charset the charset of the stream 218 * @return the infos as a List. 219 */ 220 public Object[] convertJsonToArray(InputStream jsonInput, Charset charset) 221 { 222 try (InputStreamReader reader = new InputStreamReader(jsonInput, charset); 223 JsonParser jParser = _jsonFactory.createParser(reader)) 224 { 225 return _objectMapper.readValue(jParser, Object[].class); 226 } 227 catch (Exception e) 228 { 229 throw new IllegalArgumentException("The json input can not be parsed as a Map.", e); 230 } 231 } 232 233 /** 234 * Parse a JSON string to a String array. 235 * @param jsonString the JSON string to parse. 236 * @return the converted String array. 237 */ 238 public String[] convertJsonToStringArray(String jsonString) 239 { 240 try 241 { 242 if (StringUtils.isNotBlank(jsonString)) 243 { 244 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 245 String[] array = _objectMapper.readValue(jParser, String[].class); 246 return array; 247 } 248 else 249 { 250 return new String[0]; 251 } 252 } 253 catch (Exception e) 254 { 255 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a String array.", e); 256 } 257 } 258 259 /** 260 * Parse a JSON input stream to an {@link String} array. 261 * @param jsonInput the input stream to parse 262 * @param charset the charset of the stream 263 * @return the infos as a List. 264 */ 265 public Object[] convertJsonToStringArray(InputStream jsonInput, Charset charset) 266 { 267 try (InputStreamReader reader = new InputStreamReader(jsonInput, charset); 268 JsonParser jParser = _jsonFactory.createParser(reader)) 269 { 270 return _objectMapper.readValue(jParser, String[].class); 271 } 272 catch (Exception e) 273 { 274 throw new IllegalArgumentException("The json input can not be parsed as a Map.", e); 275 } 276 } 277 278 /** 279 * Convert an object to JSON string using specified output stream. 280 * @param out The output stream 281 * @param parameters The object to convert 282 */ 283 public void convertObjectToJson (OutputStream out, Object parameters) 284 { 285 try 286 { 287 JsonGenerator jsonGenerator = _jsonFactory.createGenerator(out, JsonEncoding.UTF8); 288 _objectMapper.writeValue(jsonGenerator, parameters); 289 } 290 catch (IOException e) 291 { 292 throw new IllegalArgumentException("The object can not be converted to json string", e); 293 } 294 } 295 296 /** 297 * Convert an object to a JSON string 298 * @param parameters The object to convert (List, Map ..) 299 * @return The JSON string 300 */ 301 public String convertObjectToJson (Object parameters) 302 { 303 try 304 { 305 StringWriter writer = new StringWriter(); 306 307 JsonGenerator jsonGenerator = _jsonFactory.createGenerator(writer); 308 _objectMapper.writeValue(jsonGenerator, parameters); 309 310 return writer.toString(); 311 } 312 catch (IOException e) 313 { 314 throw new IllegalArgumentException("The object can not be converted to json string", e); 315 } 316 } 317}