Merged branch 'jetty-8' into 'master'.

This commit is contained in:
Simone Bordet 2013-07-26 13:51:26 +02:00
commit cea4ac5fe3
5 changed files with 254 additions and 135 deletions

View File

@ -39,8 +39,7 @@ import org.eclipse.jetty.util.log.Logger;
/** /**
* JSON Parser and Generator. * JSON Parser and Generator.
* * <p />
* <p>
* This class provides some static methods to convert POJOs to and from JSON * This class provides some static methods to convert POJOs to and from JSON
* notation. The mapping from JSON to java is: * notation. The mapping from JSON to java is:
* *
@ -52,9 +51,7 @@ import org.eclipse.jetty.util.log.Logger;
* null ==> null * null ==> null
* bool ==> Boolean * bool ==> Boolean
* </pre> * </pre>
*
* </p>
* <p>
* The java to JSON mapping is: * The java to JSON mapping is:
* *
* <pre> * <pre>
@ -68,30 +65,27 @@ import org.eclipse.jetty.util.log.Logger;
* Object --> string (dubious!) * Object --> string (dubious!)
* </pre> * </pre>
* *
* </p>
* <p>
* The interface {@link JSON.Convertible} may be implemented by classes that * The interface {@link JSON.Convertible} may be implemented by classes that
* wish to externalize and initialize specific fields to and from JSON objects. * wish to externalize and initialize specific fields to and from JSON objects.
* Only directed acyclic graphs of objects are supported. * Only directed acyclic graphs of objects are supported.
* </p> * <p />
* <p>
* The interface {@link JSON.Generator} may be implemented by classes that know * The interface {@link JSON.Generator} may be implemented by classes that know
* how to render themselves as JSON and the {@link #toString(Object)} method * how to render themselves as JSON and the {@link #toString(Object)} method
* will use {@link JSON.Generator#addJSON(Appendable)} to generate the JSON. * will use {@link JSON.Generator#addJSON(Appendable)} to generate the JSON.
* The class {@link JSON.Literal} may be used to hold pre-generated JSON object. * The class {@link JSON.Literal} may be used to hold pre-generated JSON object.
* <p> * <p />
* The interface {@link JSON.Convertor} may be implemented to provide static * The interface {@link JSON.Convertor} may be implemented to provide static
* convertors for objects that may be registered with * converters for objects that may be registered with
* {@link #registerConvertor(Class, org.eclipse.jetty.util.ajax.JSON.Convertor)} * {@link #registerConvertor(Class, Convertor)}.
* . These convertors are looked up by class, interface and super class by * These converters are looked up by class, interface and super class by
* {@link #getConvertor(Class)}. * {@link #getConvertor(Class)}.
* </p> * <p />
* <p>If a JSON object has a "class" field, then a java class for that name is * If a JSON object has a "class" field, then a java class for that name is
* looked up and the method {@link convertTo(Class,Map)} is used to find a * loaded and the method {@link #convertTo(Class,Map)} is used to find a
* Convertor for that class. If a JSON object has a "x-class" field then a * {@link JSON.Convertor} for that class.
* direct lookup for a Convertor for that named x-class is done, so that none * <p />
* java classes may be converted. * If a JSON object has a "x-class" field then a direct lookup for a
* </p> * {@link JSON.Convertor} for that class name is done (without loading the class).
*/ */
public class JSON public class JSON
{ {
@ -105,7 +99,6 @@ public class JSON
{ {
} }
/* ------------------------------------------------------------ */
/** /**
* @return the initial stringBuffer size to use when creating JSON strings * @return the initial stringBuffer size to use when creating JSON strings
* (default 1024) * (default 1024)
@ -115,7 +108,6 @@ public class JSON
return _stringBufferSize; return _stringBufferSize;
} }
/* ------------------------------------------------------------ */
/** /**
* @param stringBufferSize * @param stringBufferSize
* the initial stringBuffer size to use when creating JSON * the initial stringBuffer size to use when creating JSON
@ -126,7 +118,6 @@ public class JSON
_stringBufferSize = stringBufferSize; _stringBufferSize = stringBufferSize;
} }
/* ------------------------------------------------------------ */
/** /**
* Register a {@link Convertor} for a class or interface. * Register a {@link Convertor} for a class or interface.
* *
@ -140,19 +131,16 @@ public class JSON
DEFAULT.addConvertor(forClass,convertor); DEFAULT.addConvertor(forClass,convertor);
} }
/* ------------------------------------------------------------ */
public static JSON getDefault() public static JSON getDefault()
{ {
return DEFAULT; return DEFAULT;
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public static void setDefault(JSON json) public static void setDefault(JSON json)
{ {
} }
/* ------------------------------------------------------------ */
public static String toString(Object object) public static String toString(Object object)
{ {
StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize()); StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize());
@ -160,7 +148,6 @@ public class JSON
return buffer.toString(); return buffer.toString();
} }
/* ------------------------------------------------------------ */
public static String toString(Map object) public static String toString(Map object)
{ {
StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize()); StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize());
@ -168,7 +155,6 @@ public class JSON
return buffer.toString(); return buffer.toString();
} }
/* ------------------------------------------------------------ */
public static String toString(Object[] array) public static String toString(Object[] array)
{ {
StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize()); StringBuilder buffer = new StringBuilder(DEFAULT.getStringBufferSize());
@ -176,7 +162,6 @@ public class JSON
return buffer.toString(); return buffer.toString();
} }
/* ------------------------------------------------------------ */
/** /**
* @param s * @param s
* String containing JSON object or array. * String containing JSON object or array.
@ -187,7 +172,6 @@ public class JSON
return DEFAULT.parse(new StringSource(s),false); return DEFAULT.parse(new StringSource(s),false);
} }
/* ------------------------------------------------------------ */
/** /**
* @param s * @param s
* String containing JSON object or array. * String containing JSON object or array.
@ -200,7 +184,6 @@ public class JSON
return DEFAULT.parse(new StringSource(s),stripOuterComment); return DEFAULT.parse(new StringSource(s),stripOuterComment);
} }
/* ------------------------------------------------------------ */
/** /**
* @param in * @param in
* Reader containing JSON object or array. * Reader containing JSON object or array.
@ -211,7 +194,6 @@ public class JSON
return DEFAULT.parse(new ReaderSource(in),false); return DEFAULT.parse(new ReaderSource(in),false);
} }
/* ------------------------------------------------------------ */
/** /**
* @param in * @param in
* Reader containing JSON object or array. * Reader containing JSON object or array.
@ -224,7 +206,6 @@ public class JSON
return DEFAULT.parse(new ReaderSource(in),stripOuterComment); return DEFAULT.parse(new ReaderSource(in),stripOuterComment);
} }
/* ------------------------------------------------------------ */
/** /**
* @deprecated use {@link #parse(Reader)} * @deprecated use {@link #parse(Reader)}
* @param in * @param in
@ -237,7 +218,6 @@ public class JSON
return DEFAULT.parse(new StringSource(IO.toString(in)),false); return DEFAULT.parse(new StringSource(IO.toString(in)),false);
} }
/* ------------------------------------------------------------ */
/** /**
* @deprecated use {@link #parse(Reader, boolean)} * @deprecated use {@link #parse(Reader, boolean)}
* @param in * @param in
@ -252,7 +232,6 @@ public class JSON
return DEFAULT.parse(new StringSource(IO.toString(in)),stripOuterComment); return DEFAULT.parse(new StringSource(IO.toString(in)),stripOuterComment);
} }
/* ------------------------------------------------------------ */
/** /**
* Convert Object to JSON * Convert Object to JSON
* *
@ -267,7 +246,6 @@ public class JSON
return buffer.toString(); return buffer.toString();
} }
/* ------------------------------------------------------------ */
/** /**
* Convert JSON to Object * Convert JSON to Object
* *
@ -287,7 +265,6 @@ public class JSON
append((Appendable)buffer,object); append((Appendable)buffer,object);
} }
/* ------------------------------------------------------------ */
/** /**
* Append object as JSON to string buffer. * Append object as JSON to string buffer.
* *
@ -301,32 +278,58 @@ public class JSON
try try
{ {
if (object == null) if (object == null)
{
buffer.append("null"); buffer.append("null");
else if (object instanceof Convertible) }
appendJSON(buffer,(Convertible)object); // Most likely first
else if (object instanceof Generator)
appendJSON(buffer,(Generator)object);
else if (object instanceof Map) else if (object instanceof Map)
{
appendMap(buffer,(Map)object); appendMap(buffer,(Map)object);
else if (object instanceof Collection) }
appendArray(buffer,(Collection)object);
else if (object.getClass().isArray())
appendArray(buffer,object);
else if (object instanceof Number)
appendNumber(buffer,(Number)object);
else if (object instanceof Boolean)
appendBoolean(buffer,(Boolean)object);
else if (object instanceof Character)
appendString(buffer,object.toString());
else if (object instanceof String) else if (object instanceof String)
{
appendString(buffer,(String)object); appendString(buffer,(String)object);
}
else if (object instanceof Number)
{
appendNumber(buffer,(Number)object);
}
else if (object instanceof Boolean)
{
appendBoolean(buffer,(Boolean)object);
}
else if (object.getClass().isArray())
{
appendArray(buffer,object);
}
else if (object instanceof Character)
{
appendString(buffer,object.toString());
}
else if (object instanceof Convertible)
{
appendJSON(buffer,(Convertible)object);
}
else if (object instanceof Generator)
{
appendJSON(buffer,(Generator)object);
}
else else
{ {
// Check Convertor before Collection to support JSONCollectionConvertor
Convertor convertor = getConvertor(object.getClass()); Convertor convertor = getConvertor(object.getClass());
if (convertor != null) if (convertor != null)
{
appendJSON(buffer,convertor,object); appendJSON(buffer,convertor,object);
}
else if (object instanceof Collection)
{
appendArray(buffer,(Collection)object);
}
else else
{
appendString(buffer,object.toString()); appendString(buffer,object.toString());
}
} }
} }
catch (IOException e) catch (IOException e)
@ -335,14 +338,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendNull(StringBuffer buffer) public void appendNull(StringBuffer buffer)
{ {
appendNull((Appendable)buffer); appendNull((Appendable)buffer);
} }
/* ------------------------------------------------------------ */
public void appendNull(Appendable buffer) public void appendNull(Appendable buffer)
{ {
try try
@ -355,14 +356,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendJSON(final StringBuffer buffer, final Convertor convertor, final Object object) public void appendJSON(final StringBuffer buffer, final Convertor convertor, final Object object)
{ {
appendJSON((Appendable)buffer,convertor,object); appendJSON((Appendable)buffer,convertor,object);
} }
/* ------------------------------------------------------------ */
public void appendJSON(final Appendable buffer, final Convertor convertor, final Object object) public void appendJSON(final Appendable buffer, final Convertor convertor, final Object object)
{ {
appendJSON(buffer,new Convertible() appendJSON(buffer,new Convertible()
@ -378,14 +377,12 @@ public class JSON
}); });
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendJSON(final StringBuffer buffer, Convertible converter) public void appendJSON(final StringBuffer buffer, Convertible converter)
{ {
appendJSON((Appendable)buffer,converter); appendJSON((Appendable)buffer,converter);
} }
/* ------------------------------------------------------------ */
public void appendJSON(final Appendable buffer, Convertible converter) public void appendJSON(final Appendable buffer, Convertible converter)
{ {
ConvertableOutput out=new ConvertableOutput(buffer); ConvertableOutput out=new ConvertableOutput(buffer);
@ -393,27 +390,23 @@ public class JSON
out.complete(); out.complete();
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendJSON(StringBuffer buffer, Generator generator) public void appendJSON(StringBuffer buffer, Generator generator)
{ {
generator.addJSON(buffer); generator.addJSON(buffer);
} }
/* ------------------------------------------------------------ */
public void appendJSON(Appendable buffer, Generator generator) public void appendJSON(Appendable buffer, Generator generator)
{ {
generator.addJSON(buffer); generator.addJSON(buffer);
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendMap(StringBuffer buffer, Map<?,?> map) public void appendMap(StringBuffer buffer, Map<?,?> map)
{ {
appendMap((Appendable)buffer,map); appendMap((Appendable)buffer,map);
} }
/* ------------------------------------------------------------ */
public void appendMap(Appendable buffer, Map<?,?> map) public void appendMap(Appendable buffer, Map<?,?> map)
{ {
try try
@ -444,14 +437,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendArray(StringBuffer buffer, Collection collection) public void appendArray(StringBuffer buffer, Collection collection)
{ {
appendArray((Appendable)buffer,collection); appendArray((Appendable)buffer,collection);
} }
/* ------------------------------------------------------------ */
public void appendArray(Appendable buffer, Collection collection) public void appendArray(Appendable buffer, Collection collection)
{ {
try try
@ -482,14 +473,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendArray(StringBuffer buffer, Object array) public void appendArray(StringBuffer buffer, Object array)
{ {
appendArray((Appendable)buffer,array); appendArray((Appendable)buffer,array);
} }
/* ------------------------------------------------------------ */
public void appendArray(Appendable buffer, Object array) public void appendArray(Appendable buffer, Object array)
{ {
try try
@ -518,14 +507,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendBoolean(StringBuffer buffer, Boolean b) public void appendBoolean(StringBuffer buffer, Boolean b)
{ {
appendBoolean((Appendable)buffer,b); appendBoolean((Appendable)buffer,b);
} }
/* ------------------------------------------------------------ */
public void appendBoolean(Appendable buffer, Boolean b) public void appendBoolean(Appendable buffer, Boolean b)
{ {
try try
@ -535,7 +522,7 @@ public class JSON
appendNull(buffer); appendNull(buffer);
return; return;
} }
buffer.append(b.booleanValue()?"true":"false"); buffer.append(b?"true":"false");
} }
catch (IOException e) catch (IOException e)
{ {
@ -543,14 +530,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendNumber(StringBuffer buffer, Number number) public void appendNumber(StringBuffer buffer, Number number)
{ {
appendNumber((Appendable)buffer,number); appendNumber((Appendable)buffer,number);
} }
/* ------------------------------------------------------------ */
public void appendNumber(Appendable buffer, Number number) public void appendNumber(Appendable buffer, Number number)
{ {
try try
@ -568,14 +553,12 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
@Deprecated @Deprecated
public void appendString(StringBuffer buffer, String string) public void appendString(StringBuffer buffer, String string)
{ {
appendString((Appendable)buffer,string); appendString((Appendable)buffer,string);
} }
/* ------------------------------------------------------------ */
public void appendString(Appendable buffer, String string) public void appendString(Appendable buffer, String string)
{ {
if (string == null) if (string == null)
@ -589,37 +572,31 @@ public class JSON
// Parsing utilities // Parsing utilities
/* ------------------------------------------------------------ */
protected String toString(char[] buffer, int offset, int length) protected String toString(char[] buffer, int offset, int length)
{ {
return new String(buffer,offset,length); return new String(buffer,offset,length);
} }
/* ------------------------------------------------------------ */
protected Map<String, Object> newMap() protected Map<String, Object> newMap()
{ {
return new HashMap<String, Object>(); return new HashMap<String, Object>();
} }
/* ------------------------------------------------------------ */
protected Object[] newArray(int size) protected Object[] newArray(int size)
{ {
return new Object[size]; return new Object[size];
} }
/* ------------------------------------------------------------ */
protected JSON contextForArray() protected JSON contextForArray()
{ {
return this; return this;
} }
/* ------------------------------------------------------------ */
protected JSON contextFor(String field) protected JSON contextFor(String field)
{ {
return this; return this;
} }
/* ------------------------------------------------------------ */
protected Object convertTo(Class type, Map map) protected Object convertTo(Class type, Map map)
{ {
if (type != null && Convertible.class.isAssignableFrom(type)) if (type != null && Convertible.class.isAssignableFrom(type))
@ -644,7 +621,6 @@ public class JSON
return map; return map;
} }
/* ------------------------------------------------------------ */
/** /**
* Register a {@link Convertor} for a class or interface. * Register a {@link Convertor} for a class or interface.
* *
@ -658,7 +634,6 @@ public class JSON
_convertors.put(forClass.getName(),convertor); _convertors.put(forClass.getName(),convertor);
} }
/* ------------------------------------------------------------ */
/** /**
* Lookup a convertor for a class. * Lookup a convertor for a class.
* <p> * <p>
@ -677,7 +652,7 @@ public class JSON
if (convertor == null && this != DEFAULT) if (convertor == null && this != DEFAULT)
convertor = DEFAULT.getConvertor(cls); convertor = DEFAULT.getConvertor(cls);
while (convertor == null && cls != null && cls != Object.class) while (convertor == null && cls != Object.class)
{ {
Class[] ifs = cls.getInterfaces(); Class[] ifs = cls.getInterfaces();
int i = 0; int i = 0;
@ -692,7 +667,6 @@ public class JSON
return convertor; return convertor;
} }
/* ------------------------------------------------------------ */
/** /**
* Register a {@link JSON.Convertor} for a named class or interface. * Register a {@link JSON.Convertor} for a named class or interface.
* *
@ -706,7 +680,6 @@ public class JSON
_convertors.put(name,convertor); _convertors.put(name,convertor);
} }
/* ------------------------------------------------------------ */
/** /**
* Lookup a convertor for a named class. * Lookup a convertor for a named class.
* *
@ -716,14 +689,12 @@ public class JSON
*/ */
public Convertor getConvertorFor(String name) public Convertor getConvertorFor(String name)
{ {
String clsName = name; Convertor convertor = _convertors.get(name);
Convertor convertor = _convertors.get(clsName);
if (convertor == null && this != DEFAULT) if (convertor == null && this != DEFAULT)
convertor = DEFAULT.getConvertorFor(clsName); convertor = DEFAULT.getConvertorFor(name);
return convertor; return convertor;
} }
/* ------------------------------------------------------------ */
public Object parse(Source source, boolean stripOuterComment) public Object parse(Source source, boolean stripOuterComment)
{ {
int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//" int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//"
@ -811,7 +782,6 @@ public class JSON
return o; return o;
} }
/* ------------------------------------------------------------ */
public Object parse(Source source) public Object parse(Source source)
{ {
int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//" int comment_state = 0; // 0=no comment, 1="/", 2="/*", 3="/* *" -1="//"
@ -911,13 +881,11 @@ public class JSON
return null; return null;
} }
/* ------------------------------------------------------------ */
protected Object handleUnknown(Source source, char c) protected Object handleUnknown(Source source, char c)
{ {
throw new IllegalStateException("unknown char '" + c + "'(" + (int)c + ") in " + source); throw new IllegalStateException("unknown char '" + c + "'(" + (int)c + ") in " + source);
} }
/* ------------------------------------------------------------ */
protected Object parseObject(Source source) protected Object parseObject(Source source)
{ {
if (source.next() != '{') if (source.next() != '{')
@ -952,10 +920,10 @@ public class JSON
String xclassname = (String)map.get("x-class"); String xclassname = (String)map.get("x-class");
if (xclassname != null) if (xclassname != null)
{ {
Convertor c = getConvertorFor(xclassname); Convertor c = getConvertorFor(xclassname);
if (c != null) if (c != null)
return c.fromJSON(map); return c.fromJSON(map);
LOG.warn("no Convertor for xclassname '%s'", xclassname); LOG.warn("No Convertor for x-class '{}'", xclassname);
} }
String classname = (String)map.get("class"); String classname = (String)map.get("class");
@ -968,14 +936,13 @@ public class JSON
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {
LOG.warn("no Class for classname '%s'", classname); LOG.warn("No Class for '{}'", classname);
} }
} }
return map; return map;
} }
/* ------------------------------------------------------------ */
protected Object parseArray(Source source) protected Object parseArray(Source source)
{ {
if (source.next() != '[') if (source.next() != '[')
@ -1042,7 +1009,6 @@ public class JSON
throw new IllegalStateException("unexpected end of array"); throw new IllegalStateException("unexpected end of array");
} }
/* ------------------------------------------------------------ */
protected String parseString(Source source) protected String parseString(Source source)
{ {
if (source.next() != '"') if (source.next() != '"')
@ -1110,7 +1076,6 @@ public class JSON
else if (c == '\\') else if (c == '\\')
{ {
escape = true; escape = true;
continue;
} }
else if (c == '\"') else if (c == '\"')
{ {
@ -1118,7 +1083,9 @@ public class JSON
return toString(scratch,0,i); return toString(scratch,0,i);
} }
else else
{
scratch[i++] = c; scratch[i++] = c;
}
} }
// Missing end quote, but return string anyway ? // Missing end quote, but return string anyway ?
@ -1175,17 +1142,19 @@ public class JSON
else if (c == '\\') else if (c == '\\')
{ {
escape = true; escape = true;
continue;
} }
else if (c == '\"') else if (c == '\"')
{
break; break;
}
else else
{
builder.append(c); builder.append(c);
}
} }
return builder.toString(); return builder.toString();
} }
/* ------------------------------------------------------------ */
public Number parseNumber(Source source) public Number parseNumber(Source source)
{ {
boolean minus = false; boolean minus = false;
@ -1270,7 +1239,6 @@ public class JSON
} }
/* ------------------------------------------------------------ */
protected void seekTo(char seek, Source source) protected void seekTo(char seek, Source source)
{ {
while (source.hasNext()) while (source.hasNext())
@ -1287,7 +1255,6 @@ public class JSON
throw new IllegalStateException("Expected '" + seek + "'"); throw new IllegalStateException("Expected '" + seek + "'");
} }
/* ------------------------------------------------------------ */
protected char seekTo(String seek, Source source) protected char seekTo(String seek, Source source)
{ {
while (source.hasNext()) while (source.hasNext())
@ -1306,7 +1273,6 @@ public class JSON
throw new IllegalStateException("Expected one of '" + seek + "'"); throw new IllegalStateException("Expected one of '" + seek + "'");
} }
/* ------------------------------------------------------------ */
protected static void complete(String seek, Source source) protected static void complete(String seek, Source source)
{ {
int i = 0; int i = 0;
@ -1398,7 +1364,7 @@ public class JSON
_buffer.append(c); _buffer.append(c);
QuotedStringTokenizer.quote(_buffer,name); QuotedStringTokenizer.quote(_buffer,name);
_buffer.append(':'); _buffer.append(':');
appendNumber(_buffer,new Double(value)); appendNumber(_buffer, value);
c = ','; c = ',';
} }
catch (IOException e) catch (IOException e)
@ -1444,7 +1410,6 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
public interface Source public interface Source
{ {
boolean hasNext(); boolean hasNext();
@ -1456,7 +1421,6 @@ public class JSON
char[] scratchBuffer(); char[] scratchBuffer();
} }
/* ------------------------------------------------------------ */
public static class StringSource implements Source public static class StringSource implements Source
{ {
private final String string; private final String string;
@ -1500,7 +1464,6 @@ public class JSON
} }
} }
/* ------------------------------------------------------------ */
public static class ReaderSource implements Source public static class ReaderSource implements Source
{ {
private Reader _reader; private Reader _reader;
@ -1567,7 +1530,6 @@ public class JSON
} }
/* ------------------------------------------------------------ */
/** /**
* JSON Output class for use by {@link Convertible}. * JSON Output class for use by {@link Convertible}.
*/ */
@ -1586,7 +1548,6 @@ public class JSON
public void add(String name, boolean value); public void add(String name, boolean value);
} }
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* JSON Convertible object. Object can implement this interface in a similar * JSON Convertible object. Object can implement this interface in a similar
@ -1607,7 +1568,6 @@ public class JSON
public void fromJSON(Map object); public void fromJSON(Map object);
} }
/* ------------------------------------------------------------ */
/** /**
* Static JSON Convertor. * Static JSON Convertor.
* <p> * <p>
@ -1626,7 +1586,6 @@ public class JSON
public Object fromJSON(Map object); public Object fromJSON(Map object);
} }
/* ------------------------------------------------------------ */
/** /**
* JSON Generator. A class that can add it's JSON representation directly to * JSON Generator. A class that can add it's JSON representation directly to
* a StringBuffer. This is useful for object instances that are frequently * a StringBuffer. This is useful for object instances that are frequently
@ -1637,7 +1596,6 @@ public class JSON
public void addJSON(Appendable buffer); public void addJSON(Appendable buffer);
} }
/* ------------------------------------------------------------ */
/** /**
* A Literal JSON generator A utility instance of {@link JSON.Generator} * A Literal JSON generator A utility instance of {@link JSON.Generator}
* that holds a pre-generated string on JSON text. * that holds a pre-generated string on JSON text.
@ -1646,7 +1604,6 @@ public class JSON
{ {
private String _json; private String _json;
/* ------------------------------------------------------------ */
/** /**
* Construct a literal JSON instance for use by * Construct a literal JSON instance for use by
* {@link JSON#toString(Object)}. If {@link Log#isDebugEnabled()} is * {@link JSON#toString(Object)}. If {@link Log#isDebugEnabled()} is

View File

@ -40,9 +40,10 @@ import org.eclipse.jetty.util.log.Logger;
public class JSONDateConvertor implements JSON.Convertor public class JSONDateConvertor implements JSON.Convertor
{ {
private static final Logger LOG = Log.getLogger(JSONDateConvertor.class); private static final Logger LOG = Log.getLogger(JSONDateConvertor.class);
private boolean _fromJSON;
DateCache _dateCache; private final boolean _fromJSON;
SimpleDateFormat _format; private final DateCache _dateCache;
private final SimpleDateFormat _format;
public JSONDateConvertor() public JSONDateConvertor()
{ {
@ -53,7 +54,7 @@ public class JSONDateConvertor implements JSON.Convertor
{ {
this(DateCache.DEFAULT_FORMAT,TimeZone.getTimeZone("GMT"),fromJSON); this(DateCache.DEFAULT_FORMAT,TimeZone.getTimeZone("GMT"),fromJSON);
} }
public JSONDateConvertor(String format,TimeZone zone,boolean fromJSON) public JSONDateConvertor(String format,TimeZone zone,boolean fromJSON)
{ {
_dateCache=new DateCache(format); _dateCache=new DateCache(format);
@ -62,7 +63,7 @@ public class JSONDateConvertor implements JSON.Convertor
_format=new SimpleDateFormat(format); _format=new SimpleDateFormat(format);
_format.setTimeZone(zone); _format.setTimeZone(zone);
} }
public JSONDateConvertor(String format, TimeZone zone, boolean fromJSON, Locale locale) public JSONDateConvertor(String format, TimeZone zone, boolean fromJSON, Locale locale)
{ {
_dateCache = new DateCache(format, locale); _dateCache = new DateCache(format, locale);
@ -71,7 +72,7 @@ public class JSONDateConvertor implements JSON.Convertor
_format = new SimpleDateFormat(format, new DateFormatSymbols(locale)); _format = new SimpleDateFormat(format, new DateFormatSymbols(locale));
_format.setTimeZone(zone); _format.setTimeZone(zone);
} }
public Object fromJSON(Map map) public Object fromJSON(Map map)
{ {
if (!_fromJSON) if (!_fromJSON)
@ -85,7 +86,7 @@ public class JSONDateConvertor implements JSON.Convertor
} }
catch(Exception e) catch(Exception e)
{ {
LOG.warn(e); LOG.warn(e);
} }
return null; return null;
} }

View File

@ -32,7 +32,7 @@ import org.eclipse.jetty.util.log.Logger;
* If fromJSON is true in the constructor, the JSON generated will * If fromJSON is true in the constructor, the JSON generated will
* be of the form {class="com.acme.TrafficLight",value="Green"} * be of the form {class="com.acme.TrafficLight",value="Green"}
* If fromJSON is false, then only the string value of the enum is generated. * If fromJSON is false, then only the string value of the enum is generated.
* *
* *
*/ */
public class JSONEnumConvertor implements JSON.Convertor public class JSONEnumConvertor implements JSON.Convertor
@ -43,8 +43,8 @@ public class JSONEnumConvertor implements JSON.Convertor
{ {
try try
{ {
Class e = Loader.loadClass(getClass(),"java.lang.Enum"); Class<?> e = Loader.loadClass(getClass(),"java.lang.Enum");
_valueOf=e.getMethod("valueOf",new Class[]{Class.class,String.class}); _valueOf=e.getMethod("valueOf",Class.class,String.class);
} }
catch(Exception e) catch(Exception e)
{ {
@ -56,12 +56,12 @@ public class JSONEnumConvertor implements JSON.Convertor
{ {
this(false); this(false);
} }
public JSONEnumConvertor(boolean fromJSON) public JSONEnumConvertor(boolean fromJSON)
{ {
_fromJSON=fromJSON; _fromJSON=fromJSON;
} }
public Object fromJSON(Map map) public Object fromJSON(Map map)
{ {
if (!_fromJSON) if (!_fromJSON)
@ -69,11 +69,11 @@ public class JSONEnumConvertor implements JSON.Convertor
try try
{ {
Class c=Loader.loadClass(getClass(),(String)map.get("class")); Class c=Loader.loadClass(getClass(),(String)map.get("class"));
return _valueOf.invoke(null,new Object[]{c,map.get("value")}); return _valueOf.invoke(null,c,map.get("value"));
} }
catch(Exception e) catch(Exception e)
{ {
LOG.warn(e); LOG.warn(e);
} }
return null; return null;
} }
@ -83,12 +83,11 @@ public class JSONEnumConvertor implements JSON.Convertor
if (_fromJSON) if (_fromJSON)
{ {
out.addClass(obj.getClass()); out.addClass(obj.getClass());
out.add("value",obj.toString()); out.add("value",((Enum)obj).name());
} }
else else
{ {
out.add(obj.toString()); out.add(((Enum)obj).name());
} }
} }
} }

View File

@ -0,0 +1,50 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.ajax;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import org.eclipse.jetty.util.Loader;
public class JSONCollectionConvertor implements JSON.Convertor
{
public void toJSON(Object obj, JSON.Output out)
{
out.addClass(obj.getClass());
out.add("list", ((Collection)obj).toArray());
}
public Object fromJSON(Map object)
{
try
{
Collection result = (Collection)Loader.loadClass(getClass(), (String)object.get("class")).newInstance();
Collections.addAll(result, (Object[])object.get("list"));
return result;
}
catch (Exception x)
{
if (x instanceof RuntimeException)
throw (RuntimeException)x;
throw new RuntimeException(x);
}
}
}

View File

@ -0,0 +1,112 @@
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.ajax;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CopyOnWriteArrayList;
import org.junit.Assert;
import org.junit.Test;
public class JSONCollectionConvertorTest
{
@Test
public void testArrayList() throws Exception
{
List<String> list = new ArrayList<String>();
Collections.addAll(list, "one", "two");
testList(list);
}
@Test
public void testLinkedList() throws Exception
{
List<String> list = new LinkedList<String>();
Collections.addAll(list, "one", "two");
testList(list);
}
@Test
public void testCopyOnWriteArrayList() throws Exception
{
List<String> list = new CopyOnWriteArrayList<String>();
Collections.addAll(list, "one", "two");
testList(list);
}
private void testList(List<String> list1) throws Exception
{
JSON json = new JSON();
json.addConvertor(List.class, new JSONCollectionConvertor());
Map<String, Object> object1 = new HashMap<String, Object>();
String field = "field";
object1.put(field, list1);
String string = json.toJSON(object1);
Assert.assertTrue(string.contains(list1.getClass().getName()));
@SuppressWarnings("unchecked")
Map<String, Object> object2 = (Map<String, Object>)json.parse(new JSON.StringSource(string));
@SuppressWarnings("unchecked")
List<String> list2 = (List<String>)object2.get(field);
Assert.assertSame(list1.getClass(), list2.getClass());
Assert.assertEquals(list1, list2);
}
@Test
public void testHashSet() throws Exception
{
Set<String> set = new HashSet<String>();
Collections.addAll(set, "one", "two", "three");
testSet(set);
}
@Test
public void testTreeSet() throws Exception
{
Set<String> set = new TreeSet<String>();
Collections.addAll(set, "one", "two", "three");
testSet(set);
}
private void testSet(Set<String> set1)
{
JSON json = new JSON();
json.addConvertor(Set.class, new JSONCollectionConvertor());
String string = json.toJSON(set1);
Assert.assertTrue(string.contains(set1.getClass().getName()));
@SuppressWarnings("unchecked")
Set<String> set2 = (Set<String>)json.parse(new JSON.StringSource(string));
Assert.assertSame(set1.getClass(), set2.getClass());
Assert.assertEquals(set1, set2);
}
}