Hello guys,
if you are looking for a solution to convert your configuration classes into json files, here is a quick ready-to-use example, among the many you could find on the web. In particular, I focused on the serialization and deserialization of the ColorRGBA, Vector3f and Quaternion jme classes.
The libraries I used are:
- jackson-annotation-2.9.0.jar
- jackson-core-2.9.8.jar
- jackson-databind-2.9.8.jar
To simplify the configuration of the ObjectMapper, I centralized all the serializers into a single reusable JmeJsonModule class which extends SimpleModule. This way I have a complete and clear view of how information is encoded / decoded in a single file without having to create a class for each serializer (see also the method: setupModule(SetupContext context) )
Hope this was helpful, let me know if you have used a better solution.
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.module.SimpleSerializers;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
public class JmeJsonModule extends SimpleModule {
private static final long serialVersionUID = 1L;
class QuaternionDeserializer extends JsonDeserializer<Quaternion> {
@Override
public Quaternion deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
// TODO Auto-generated method stub
float[] values = parser.readValueAs(float[].class);
return new Quaternion(values[0], values[1], values[2], values[3]);
}
}
class QuaternionSerializer extends JsonSerializer<Quaternion> {
@Override
public void serialize(Quaternion quat, JsonGenerator gen, SerializerProvider provider) throws IOException {
// TODO Auto-generated method stub
gen.writeStartArray(4);
gen.writeNumber(quat.getX());
gen.writeNumber(quat.getY());
gen.writeNumber(quat.getZ());
gen.writeNumber(quat.getW());
gen.writeEndArray();
}
}
class Vector3Deserializer extends JsonDeserializer<Vector3f> {
@Override
public Vector3f deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
// TODO Auto-generated method stub
float[] values = parser.readValueAs(float[].class);
return new Vector3f(values[0], values[1], values[2]);
}
}
class Vector3Serializer extends JsonSerializer<Vector3f> {
@Override
public void serialize(Vector3f vec, JsonGenerator gen, SerializerProvider provider) throws IOException {
// TODO Auto-generated method stub
gen.writeStartArray(3);
gen.writeNumber(vec.getX());
gen.writeNumber(vec.getY());
gen.writeNumber(vec.getZ());
gen.writeEndArray();
}
}
class ColorDeserializer extends JsonDeserializer<ColorRGBA> {
@Override
public ColorRGBA deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException {
// TODO Auto-generated method stub
float[] values = parser.readValueAs(float[].class);
return new ColorRGBA(values[0], values[1], values[2], values[3]);
}
}
class ColorSerializer extends JsonSerializer<ColorRGBA> {
@Override
public void serialize(ColorRGBA color, JsonGenerator gen, SerializerProvider provider) throws IOException {
// TODO Auto-generated method stub
gen.writeStartArray(4);
gen.writeNumber(color.getRed());
gen.writeNumber(color.getGreen());
gen.writeNumber(color.getBlue());
gen.writeNumber(color.getAlpha());
gen.writeEndArray();
}
}
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
SimpleSerializers ser = new SimpleSerializers();
ser.addSerializer(Quaternion.class, new QuaternionSerializer());
ser.addSerializer(Vector3f.class, new Vector3Serializer());
ser.addSerializer(ColorRGBA.class, new ColorSerializer());
context.addSerializers(ser);
SimpleDeserializers des = new SimpleDeserializers();
des.addDeserializer(Quaternion.class, new QuaternionDeserializer());
des.addDeserializer(Vector3f.class, new Vector3Deserializer());
des.addDeserializer(ColorRGBA.class, new ColorDeserializer());
context.addDeserializers(des);
}
}
Here my example bean class filled with random values:
public class MyBean {
public HumanBodyBones humanBone;
public String boneName;
public Vector3f position;
public Quaternion rotation;
public ColorRGBA color;
public MyBean() {
HumanBodyBones[] values = HumanBodyBones.values();
humanBone = values[FastMath.nextRandomInt(0, values.length - 1)];
boneName = "Armature_mixamorig:" + humanBone.getBoneName();
position = getRandomPosition();
rotation = Quaternion.IDENTITY;
color = ColorRGBA.randomColor();
}
private Vector3f getRandomPosition() {
float x = FastMath.nextRandomFloat();
float y = FastMath.nextRandomFloat();
float z = FastMath.nextRandomFloat();
return new Vector3f(x, y, z);
}
@Override
public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
And here the Main class to lunch the test:
public class Test_Json {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JmeJsonModule());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
List<MyBean> lstInput = Arrays.asList(new MyBean(), new MyBean(), new MyBean());
String json = mapper.writeValueAsString(lstInput);
System.out.println(json);
// Unmarshall to Collection
// List<MyBean> lstOutput = mapper.readValue(json, new TypeReference<List<MyBean>>(){});
// Unmarshall to Array
MyBean[] array = mapper.readValue(json, MyBean[].class);
System.out.println(Arrays.toString(array));
}
And here the output:
[ {
"humanBone" : "LEFT_SHOULDER",
"boneName" : "Armature_mixamorig:LeftShoulder",
"position" : [ 0.83388364, 0.39985967, 0.01943177 ],
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ],
"color" : [ 0.42542416, 0.20122874, 0.7825847, 1.0 ]
}, {
"humanBone" : "LEFT_SHOULDER",
"boneName" : "Armature_mixamorig:LeftShoulder",
"position" : [ 0.31399703, 0.5166057, 0.88700897 ],
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ],
"color" : [ 0.8347665, 0.61224395, 0.30979508, 1.0 ]
}, {
"humanBone" : "SPINE_1",
"boneName" : "Armature_mixamorig:Spine1",
"position" : [ 0.35129148, 0.87165403, 0.20744377 ],
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ],
"color" : [ 0.644656, 0.9456146, 0.010902762, 1.0 ]
} ]
[Test_Json.MyBean[
humanBone=LEFT_SHOULDER,
boneName=Armature_mixamorig:LeftShoulder,
color=Color[0.42542416, 0.20122874, 0.7825847, 1.0],
position=(0.83388364, 0.39985967, 0.01943177),
rotation=(0.0, 0.0, 0.0, 1.0)],
Test_Json.MyBean[
humanBone=LEFT_SHOULDER,
boneName=Armature_mixamorig:LeftShoulder,
color=Color[0.8347665, 0.61224395, 0.30979508, 1.0],
position=(0.31399703, 0.5166057, 0.88700897),
rotation=(0.0, 0.0, 0.0, 1.0)],
Test_Json.MyBean[
humanBone=SPINE_1,
boneName=Armature_mixamorig:Spine1,
color=Color[0.644656, 0.9456146, 0.010902762, 1.0],
position=(0.35129148, 0.87165403, 0.20744377),
rotation=(0.0, 0.0, 0.0, 1.0)]]