[Json-rpc-java] Support for enum
Connor Barry
connor at slickapps.com
Thu Jan 25 00:55:42 SGT 2007
Jeff,
I had to write my own. It's pretty much a quick hack solution but works
OK for me - I assume the next version will supported enums explicitly.
There's two catches:
1 - The enum's actual name will be assigned to the "_name" attribute, to
allow you to have another field in the enum called "name". So out in
your javascript, refer to the actual name with "theObj._name"
2 - You have to explicitly populate an array of all the possible
enumerated type classes
---------------------------------------------------------------------------------------
package com.yourcompany.web.jsonrpc;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.json.JSONObject;
import com.metaparadigm.jsonrpc.AbstractSerializer;
import com.metaparadigm.jsonrpc.MarshallException;
import com.metaparadigm.jsonrpc.ObjectMatch;
import com.metaparadigm.jsonrpc.SerializerState;
import com.metaparadigm.jsonrpc.UnmarshallException;
public class EnumSerializer extends AbstractSerializer {
private final static Logger log =
Logger.getLogger(EnumSerializer.class);
private static final long serialVersionUID = 1L;
private static Class[] _JSONClasses = new Class[] { JSONObject.class };
private Class[] serializableClasses;
public Class[] getJSONClasses() {
return _JSONClasses;
}
public Object marshall(SerializerState state, Object o) throws
MarshallException {
try {
for (Class<? extends Enum> clazz : getSerializableClasses()) {
if (!clazz.isInstance(o)) continue;
Enum theEnum = clazz.cast(o);
JSONObject jso = new JSONObject();
jso.put("_name", theEnum.name());
if (ser.getMarshallClassHints()) jso.put("javaClass",
theEnum.getClass().getName());
BeanInfo info = Introspector.getBeanInfo(clazz);
PropertyDescriptor props[] = info.getPropertyDescriptors();
for (PropertyDescriptor prop : props) {
if ("declaringClass".equals(prop.getName()) ||
"class".equals(prop.getName()))
continue;
Method readMethod = prop.getReadMethod();
if (readMethod == null) continue;
if (ser.isDebug()) log.debug("invoking " +
readMethod.getName() + "()");
Object result;
try {
result = readMethod.invoke(o, (Object[]) null);
} catch (Throwable e) {
if (e instanceof InvocationTargetException)
e = ((InvocationTargetException)
e).getTargetException();
throw new MarshallException("bean " +
o.getClass().getName() + " can't invoke "
+ readMethod.getName() + ": " +
e.getMessage());
}
try {
if (result != null ||
ser.getMarshallNullAttributes())
jso.put(prop.getName(), ser.marshall(state,
result));
} catch (MarshallException e) {
throw new MarshallException("bean " +
o.getClass().getName() + " "
+ e.getMessage());
}
}
return jso;
}
} catch (IntrospectionException e) {
e.printStackTrace();
throw new MarshallException("There was an exception while
inspecting the class "
+ o.getClass().getName() + ", see stdout");
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new MarshallException("There was an exception while
inspecting the class "
+ o.getClass().getName() + ", see stdout");
}
throw new MarshallException("The specified object (" +
o.getClass().getName()
+ ") was not an instance of any of the serializable
classes");
}
@SuppressWarnings("unchecked")
public Object unmarshall(SerializerState state, Class clazz, Object o)
throws UnmarshallException {
JSONObject jso = (JSONObject) o;
String name = jso.getString("_name");
if (name == null)
throw new UnmarshallException("The specified JSONObject of
type " + clazz.getName()
+ " didn't contain a _name attribute");
return Enum.valueOf(clazz, name);
}
public ObjectMatch tryUnmarshall(SerializerState arg0, Class arg1,
Object arg2) {
return null;
}
/**
* @return the serializableClasses
*/
public Class[] getSerializableClasses() {
return serializableClasses;
}
/**
* @param serializableClasses the serializableClasses to set
*/
public void setSerializableClasses(Class[] serializableClasses) {
this.serializableClasses = serializableClasses;
}
}
------------------------------------------------------------------------
You also need to register this serializer with the bridge, either the
global bridge once in a static block, or every time a new
HTTPSession-specific bridge gets created and put in the user's HTTP Session:
EnumSerializer enumSerializer = new EnumSerializer();
enumSerializer.setSerializableClasses(new Class[] {MyEnumeratedType.class});
bridge.registerSerializer(enumSerializer);
I might have forgotten something, send questions to the list.
Connor
Jeff Moody wrote:
> I was wondering if there are any plans to support enum types.
> E.g. I have a class with a property that is a defined enum type, where the
> enum has declared constants of that type.
> I have a method that returns one of these objects, but when calling the
> method through the bridge, it gives me a Javascript error of an unhandled
> JSONRpc exception, indicating the error is due to a circular reference.
>
> For example, say the following declaration is in foo.java:
> public enum Foo {
> VALUE1
> , VALUE2
> }
>
>
> Returning an object with a Foo property causes an error.
>
> Are there any workarounds to this?
>
> Thanks,
> -Jeff
>
>
> _______________________________________________
> Json-rpc-java mailing list
> Json-rpc-java at oss.metaparadigm.com
> http://oss.metaparadigm.com/mailman/listinfo/json-rpc-java
>
More information about the Json-rpc-java
mailing list