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