2
\$\begingroup\$

I have a collection of serialized components in JSON format:

{
    "components": [{
        "class": "com.package.component.PositionComponent",
        "x": 100,
        "y": 100
    }, {
        "class": "com.package.component.VelocityComponent",
        "x": 4,
        "y": 2
    }]
}

I want to load this into a collection of base Components in Java, specifically into an Entity. I am currently using YAML (parsed using SnakeYAML) to achieve this. The following file (which is virtually identical to the JSON one) is parsed and the components are stored in an ArrayList:

components:
- ==: com.package.component.PositionComponent
  x: 100
  y: 100
- ==: com.package.component.VelocityComponent
  x: 4
  y: 2

Is there any way I can achieve this using the JSON parsing facilities provided by LibGDX? I am currently using the following code to parse the components, but I have no idea how to get it to construct the correct appropriate object for each component:

JsonReader reader = new JsonReader();
JsonValue base = reader.parse("components.json");

for (JsonValue component : base.get("components")) {
    System.out.println(component.getString("class"));
}
\$\endgroup\$
  • \$\begingroup\$ Is there a reason you cannot use a map/dictionary from component name to a function/delegate/etc that creates the desired type of component (basically a factory? \$\endgroup\$ – Josh Aug 2 '16 at 19:52
  • \$\begingroup\$ I'm more or less wondering if there is an equivalent to SnakeYAML's method of doing this. \$\endgroup\$ – driima Aug 2 '16 at 19:53
1
\$\begingroup\$

So are you asking how to create a class given a class type as a string?

JsonReader reader = new JsonReader();
JsonValue base = reader.parse("components.json");

for (JsonValue component : base.get("components")) {
    Class<?> clazz = Class.forName(component.getString("class"));
    Constructor<?> ctor = clazz.getConstructor();
    Object object = ctor.newInstance();
}

Though I assume you probably have no arg consructors, if you need to pass arguments to a constructor, it is done like this (if the argument was a String):

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });
\$\endgroup\$
  • \$\begingroup\$ Which is appropriate for deserializing JSON into known objects. It won't work, however, if I want to deserialize an array of components to be stored in a collection such as ArrayList<? extends Component>, such that I don't know the exact type of component I am deserializing. \$\endgroup\$ – driima Aug 3 '16 at 1:00
  • \$\begingroup\$ My bad. I updated my answer with attempt #2 \$\endgroup\$ – spectacularbob Aug 3 '16 at 16:23
  • \$\begingroup\$ Also object can be declared of type Entity, instead of Object, as the OP specified. \$\endgroup\$ – clabe45 Aug 16 '17 at 23:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.