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.OutputStream; 021import java.io.StringReader; 022import java.io.StringWriter; 023import java.util.ArrayList; 024import java.util.LinkedHashMap; 025import java.util.List; 026import java.util.Map; 027 028import org.apache.avalon.framework.activity.Initializable; 029import org.apache.avalon.framework.component.Component; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.avalon.framework.service.Serviceable; 033import org.apache.avalon.framework.thread.ThreadSafe; 034import org.apache.commons.io.IOUtils; 035import org.apache.commons.lang.StringUtils; 036 037import org.ametys.plugins.core.ui.help.HelpSerializer; 038 039import com.fasterxml.jackson.core.JsonEncoding; 040import com.fasterxml.jackson.core.JsonFactory; 041import com.fasterxml.jackson.core.JsonGenerator; 042import com.fasterxml.jackson.core.JsonParser; 043import com.fasterxml.jackson.core.Version; 044import com.fasterxml.jackson.databind.ObjectMapper; 045import com.fasterxml.jackson.databind.module.SimpleModule; 046 047/** 048 * JSON helper 049 */ 050public class JSONUtils implements Component, ThreadSafe, Serviceable, Initializable 051{ 052 /** The avalon role */ 053 public static final String ROLE = JSONUtils.class.getName(); 054 055 private JsonFactory _jsonFactory = new JsonFactory(); 056 private ObjectMapper _objectMapper = new ObjectMapper(); 057 058 private I18nizableTextSerializer _i18nizableTextSerializer; 059 private HelpSerializer _helpSerializer; 060 private ZonedDateTimeSerializer _zoneDateTimeSerializer; 061 private LocalDateSerializer _localDateSerializer; 062 063 @Override 064 public void service(ServiceManager manager) throws ServiceException 065 { 066 _i18nizableTextSerializer = (I18nizableTextSerializer) manager.lookup(I18nizableTextSerializer.ROLE); 067 _zoneDateTimeSerializer = (ZonedDateTimeSerializer) manager.lookup(ZonedDateTimeSerializer.ROLE); 068 _localDateSerializer = (LocalDateSerializer) manager.lookup(LocalDateSerializer.ROLE); 069 _helpSerializer = (HelpSerializer) manager.lookup(HelpSerializer.ROLE); 070 } 071 072 @Override 073 public void initialize() throws Exception 074 { 075 // Register new serializer for I18nizableText 076 SimpleModule i18nModule = new SimpleModule("AmetysI18nModule", new Version(1, 0, 0, null, null, null)); 077 i18nModule.addSerializer(_i18nizableTextSerializer); 078 _objectMapper.registerModule(i18nModule); 079 080 // Register new serializer for help url 081 SimpleModule helpModule = new SimpleModule("AmetysHelpModule", new Version(1, 0, 0, null, null, null)); 082 helpModule.addSerializer(_helpSerializer); 083 _objectMapper.registerModule(helpModule); 084 085 // Register new serializer for ZonedDateTime 086 SimpleModule zoneDateTimeModule = new SimpleModule("AmetysZonedDateTimeModule", new Version(1, 0, 0, null, null, null)); 087 zoneDateTimeModule.addSerializer(_zoneDateTimeSerializer); 088 _objectMapper.registerModule(zoneDateTimeModule); 089 090 // Register new serializer for LocalDate 091 SimpleModule localDateModule = new SimpleModule("AmetysLocalDateModule", new Version(1, 0, 0, null, null, null)); 092 localDateModule.addSerializer(_localDateSerializer); 093 _objectMapper.registerModule(localDateModule); 094 } 095 096 /** 097 * Parse a JSON string to a {@link Map} object 098 * @param jsonString the string to parse 099 * @return object the infos as a Map. 100 */ 101 public Map<String, Object> convertJsonToMap (String jsonString) 102 { 103 try 104 { 105 if (StringUtils.isNotBlank(jsonString)) 106 { 107 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 108 Map<String, Object> map = _objectMapper.readValue(jParser, LinkedHashMap.class); 109 return map; 110 } 111 else 112 { 113 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 114 } 115 } 116 catch (Exception e) 117 { 118 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a Map.", e); 119 } 120 } 121 122 /** 123 * Parse a JSON string to a {@link List} object. 124 * @param jsonString the string to parse. 125 * @return the infos as a List. 126 */ 127 public List<Object> convertJsonToList(String jsonString) 128 { 129 try 130 { 131 if (StringUtils.isNotBlank(jsonString)) 132 { 133 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 134 List<Object> list = _objectMapper.readValue(jParser, ArrayList.class); 135 return list; 136 } 137 else 138 { 139 return new ArrayList<>(); 140 } 141 } 142 catch (Exception e) 143 { 144 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a List.", e); 145 } 146 } 147 148 /** 149 * Parse a JSON string to an Object array. 150 * @param jsonString the JSON string to parse. 151 * @return the converted Object array. 152 */ 153 public Object[] convertJsonToArray(String jsonString) 154 { 155 try 156 { 157 if (StringUtils.isNotBlank(jsonString)) 158 { 159 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 160 Object[] array = _objectMapper.readValue(jParser, Object[].class); 161 return array; 162 } 163 else 164 { 165 return new Object[0]; 166 } 167 } 168 catch (Exception e) 169 { 170 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as an array.", e); 171 } 172 } 173 174 /** 175 * Parse a JSON string to a String array. 176 * @param jsonString the JSON string to parse. 177 * @return the converted String array. 178 */ 179 public String[] convertJsonToStringArray(String jsonString) 180 { 181 try 182 { 183 if (StringUtils.isNotBlank(jsonString)) 184 { 185 JsonParser jParser = _jsonFactory.createParser(new StringReader(jsonString)); 186 String[] array = _objectMapper.readValue(jParser, String[].class); 187 return array; 188 } 189 else 190 { 191 return new String[0]; 192 } 193 } 194 catch (Exception e) 195 { 196 throw new IllegalArgumentException("The json string " + jsonString + " can not be parsed as a String array.", e); 197 } 198 } 199 200 /** 201 * Convert an object to JSON string using specified output stream. 202 * The out stream is closed after processing. 203 * @param out The output stream 204 * @param parameters The object to convert 205 */ 206 public void convertObjectToJson (OutputStream out, Object parameters) 207 { 208 try 209 { 210 JsonGenerator jsonGenerator = _jsonFactory.createGenerator(out, JsonEncoding.UTF8); 211 _objectMapper.writeValue(jsonGenerator, parameters); 212 213 IOUtils.closeQuietly(out); 214 } 215 catch (IOException e) 216 { 217 throw new IllegalArgumentException("The object can not be converted to json string", e); 218 } 219 } 220 221 /** 222 * Convert an object to a JSON string 223 * @param parameters The object to convert (List, Map ..) 224 * @return The JSON string 225 */ 226 public String convertObjectToJson (Object parameters) 227 { 228 try 229 { 230 StringWriter writer = new StringWriter(); 231 232 JsonGenerator jsonGenerator = _jsonFactory.createGenerator(writer); 233 _objectMapper.writeValue(jsonGenerator, parameters); 234 235 return writer.toString(); 236 } 237 catch (IOException e) 238 { 239 throw new IllegalArgumentException("The object can not be converted to json string", e); 240 } 241 } 242}