/***************************************************************************
* Copyright (C) 2011 by Fabrizio Montesi <famontesi@gmail.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Library General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* For details about the authors of this software, see the AUTHORS file. *
***************************************************************************/
package jolie.net.http.json;
import java.io.IOException;
import java.io.Reader;
import java.util.Map;
import java.util.Map.Entry;
import jolie.runtime.Value;
import jolie.runtime.ValueVector;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
/**
*
* @author Fabrizio Montesi
*/
public class JsonUtils
{
private final static String ROOT_SIGN = "$";
public static void valueToJsonString( Value value, StringBuilder builder )
throws IOException
{
if ( value.children().isEmpty() ) {
if ( value.isDefined() ) {
builder.append( nativeValueToJsonString( value ) );
}
} else {
builder.append( '{' );
if ( value.isDefined() ) {
appendKeyColon( builder, ROOT_SIGN );
builder.append( nativeValueToJsonString( value ) );
}
int size = value.children().size();
int i = 0;
for( Entry< String, ValueVector > child : value.children().entrySet() ) {
if ( child.getValue().isEmpty() == false ) {
appendKeyColon( builder, child.getKey() );
valueVectorToJsonString( child.getValue(), builder );
}
if ( i++ < size - 1 ) {
builder.append( ',' );
}
}
builder.append( '}' );
}
}
private static void valueVectorToJsonString( ValueVector vector, StringBuilder builder )
throws IOException
{
if ( vector.size() > 1 ) {
builder.append( '[' );
for( int i = 0; i < vector.size(); i++ ) {
valueToJsonString( vector.get( i ), builder );
if ( i < vector.size() - 1 ) {
builder.append( ',' );
}
}
builder.append( ']' );
} else {
valueToJsonString( vector.first(), builder );
}
}
private static void appendKeyColon( StringBuilder builder, String key )
{
builder.append( '"' )
.append( key )
.append( "\":" );
}
private static String nativeValueToJsonString( Value value )
throws IOException
{
if ( value.isInt() || value.isDouble() ) {
return value.strValue();
} else {
return '"' + JSONValue.escape( value.strValue() ) + '"';
}
}
public static void parseJsonIntoValue( Reader reader, Value value )
throws IOException
{
try {
jsonObjectToValue( (JSONObject)JSONValue.parseWithException( reader ), value );
} catch( ParseException e ) {
throw new IOException( e );
} catch( ClassCastException e ) {
throw new IOException( e );
}
}
private static void jsonObjectToValue( JSONObject obj, Value value )
{
Map< String, Object > map = (Map< String, Object >)obj;
ValueVector vec;
for( Entry< String, Object > entry : map.entrySet() ) {
if ( entry.getKey().equals( ROOT_SIGN ) ) {
if ( entry.getValue() instanceof String ) {
value.setValue( (String) entry.getValue() );
} else if ( entry.getValue() instanceof Double ) {
value.setValue( (Double)entry.getValue() );
} else if ( entry.getValue() instanceof Integer ) {
value.setValue( (Integer)entry.getValue() );
} else if ( entry.getValue() instanceof Long ) {
value.setValue( ((Long)entry.getValue()).intValue() );
} else if ( entry.getValue() instanceof Boolean ){
Boolean b = (Boolean)entry.getValue();
if ( b ) {
value.setValue( 1 );
} else {
value.setValue( 0 );
}
} else {
value.setValue( entry.getValue().toString() );
}
} else {
vec = jsonObjectToValueVector( entry.getValue() );
value.children().put( entry.getKey(), vec );
}
}
}
private static ValueVector jsonObjectToValueVector( Object obj )
{
ValueVector vec = ValueVector.create();
if ( obj instanceof JSONObject ) {
Value val = Value.create();
jsonObjectToValue( (JSONObject)obj, val );
vec.add( val );
} else if ( obj instanceof JSONArray ) {
JSONArray array = (JSONArray) obj;
for ( Object element : array ) {
if ( element instanceof JSONObject ) {
Value val = Value.create();
jsonObjectToValue( (JSONObject)element, val );
vec.add( val );
} else {
vec.add( getBasicValue( element ) );
}
}
} else {
vec.add( getBasicValue( obj ) );
}
return vec;
}
private static Value getBasicValue( Object obj )
{
Value val = Value.create();
if ( obj instanceof String ) {
val.setValue( (String) obj );
} else if ( obj instanceof Double ) {
val.setValue( (Double) obj );
} else if ( obj instanceof Integer ) {
val.setValue( (Integer) obj );
} else if ( obj instanceof Long ) {
val.setValue( ((Long) obj).intValue() );
} else if ( obj instanceof Boolean ) {
Boolean b = (Boolean) obj;
if ( b ) {
val.setValue( 1 );
} else {
val.setValue( 0 );
}
} else {
val.setValue( obj.toString() );
}
return val;
}
}