we are creating a JSON REST client application that has to communicate with a service written in C#. Most things like difference in dates etc are solved pretty easily with the FlexJson library.
But one thing doesn't: Enum values that are sent as an integer, which is the value received from the service, and that have to be mapped to their Java Enum value.
The Java enum is ok, we can convert integers to the enum as long as the value exists of course. But we do not succeed to get the Flexjson to convert the value.
One of the Enums is called FormState
We wrote a custom Transformer let's call it OurEnumTransformer which extends AbstractTransformer and implements ObjectFactory. Upon deserialization we add the .use(Enum.class, OurEnumTransformer), if we don't we get an error like:
Don't know how to convert 4 to enumerated constant of FormState
which makes sense as it is an integer and not a name of an enum value
But we add the .use(...) we keep getting an error on deserialization:
FormState lacks a no argument constructor. Flexjson will instantiate any protected, private, or public no-arg constructor.
But it does actually have a private parameterless constructor.
Another thing is that a breakpoint that is set in the OurEnumTransformer is never hit.
So can anyone help me why .use(Enum.class, OurEnumTransformer) does not work with an enum that has integer values?
The code of the enum and OurEnumTransformeris below
public enum FormState {
None(0),
EditMode(1),
SignedBySender(2),
AddedToRide(4),
SignedByTransporter(8),
SignedByReceiver(16),
DLT_UNKNOWN();
private int value;
private FormState() {
this.value= -1;
}
private FormState(int value) {
this.value= value;
}
public int getValue()
{
return value;
}
private static final Map<Integer, FormState> intToTypeMap = new HashMap<Integer, FormState>();
static
{
for(FormState type: FormState.values())
{
intToTypeMap.put(type.value, type);
}
}
public static FormState fromInt(int i) {
FormState type = intToTypeMap.get(Integer.valueOf(i));
if (type == null)
return FormState.DLT_UNKNOWN;
return type;
}
}
and the factory
public final class OurEnumTransformer extends AbstractTransformer implements
ObjectFactory {
@SuppressWarnings("rawtypes")
@Override
public Object instantiate(ObjectBinder context, Object value, Type targetType,
Class targetClass)
{
if(targetClass.equals(FormState.class))
return FormState.fromInt((Integer)value);
else if(targetClass.equals(TrajectState.class))
return TrajectState.fromInt((Integer)value);
else
throw new JSONException(String.format("%s: Don't know how to convert %s to enumerated constant of %s",
context.getCurrentPath(), value, targetType));
}
@Override
public void transform(Object arg0) {
// TODO Auto-generated method stub
}
}
finally the calling code:
List<JsonTrajectModel> result = null;
JSONDeserializer<List<JsonTrajectModel>> deser = new JSONDeserializer<List<JsonTrajectModel>>();
result = deser
.use(Date.class, dateTransformer)
.use("values", JsonTrajectModel.class)
.use(Enum.class, enumTransformer)
.deserialize(jsonData);
In the last code block jsonData is a valid JSON string and enumTransformer is the OurEnumTransformer instance.
A final remark, the dateTransformer used in this code does do its work.
Any help is appreciated.