B: easier to use standalone json node
As the other answers say, I would go to B because of encapsulation, but I will give one more pragmatic reason: think about what the general process that you develop yourself will do, or if you use the library: I will use Jackson " (maybe it can be used on Android).
- If the type is outside the JsonNode that you are analyzing, you need to specify in the deserializer for each property where the type is located, if it is inside the same Node, you only specify where the type is "inside the object", and for many objects it can to be the same.
- An additional argument, if you pass only the “battle” object, it does not have a container, so there are no external properties to indicate the type
- Another argument, at least 1 JS library uses this method: ExtJS, see the "xtype" property in the documentation http://docs.sencha.com/extjs/5.0.1/guides/getting_started/getting_started.html
So here is the Node you want to parse with a good type:
{ "type": "BATTLE", "aPropertyOfBattle":1 }
here is the jackson code for this
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes ({ @JsonSubTypes.Type (Battle.class), //...all your types }) public interface ICustomType {} @JsonTypeName("BATTLE") public class Battle implements ICustomType{ int aPropertyOfBattle; // getters/setters... }
jackson provides a solution for "gessing" type:
Full working code:
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type") @JsonSubTypes ({ @JsonSubTypes.Type (Battle.class), //...all your types }) public interface ICustomType {} @JsonTypeName("BATTLE") public class Battle implements ICustomType{ int aPropertyOfBattle; // getters setters... } public class BattleContainer { private ICustomType template; private String id; private String name; // getters/setters } public class BattleTest { @Test public void testBattle() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); ICustomType battle = objectMapper.readValue("{'type': 'BATTLE','aPropertyOfBattle':1}".replace('\'','"'),Battle.class ); Assert.assertTrue("Instance of battle",battle instanceof Battle); Assert.assertEquals(((Battle)battle).getaPropertyOfBattle(),1); } @Test public void testBattleContainer() throws IOException { ObjectMapper objectMapper = new ObjectMapper(); BattleContainer battleContainer = objectMapper.readValue("{'id': 'A001','name': 'My First Game','template': {'type': 'BATTLE', 'aPropertyOfBattle':1}}" .replace('\'','"'),BattleContainer.class ); Assert.assertTrue("Instance of battle",battleContainer.getTemplate() instanceof Battle); Assert.assertEquals(((Battle)battleContainer.getTemplate()).getaPropertyOfBattle(),1); } }
Note that this is not a specific Jackson, you can parse Node with a simple JsonNode in java.
Editing: I see that this may seem off topic as I give a technical solution, so I clarify that the argument here is not to use Jackson, it should show that regardless of the language of the solution and the library you choose, It is possible to use the “B” solution in an elegant way.
D: node encapsulation Another solution is the following:
{ "BATTLE":{ "aPropertyOfBattle":1 } }
It may be easier to analyze: you get the name of the property, then you parse under the node using any tool (Gson or another ...) In Jackson, the only difference is that you use include = As.WRAPPER_OBJECT
The inconvenient thing in Javascript is less logical to use, since you have a useless Node in the middle of your structure.
Another Jackson Solution
This library as other options include = As....
- As.WRAPPER_ARRAY
As.EXTERNAL_PROPERTY
WRAPPER_ARRAY easier to parse, but I don't find it elegant (this is completely subjective):
[ "BATTLE", { "aPropertyOfBattle":1 } ]
EXTERNAL_PROPERTY will be A. solution, but, as I said, you should specify it every time you use your variable, and not in your type class (I do not have consistency with me, because you can use the Battle object in another context, with another naming convention)
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = As.EXTERNAL_PROPERTY, property = "template_type") private ICustomType template;
Remember once again, I am inspired by the functionality of Jackson, but it can be applied to every solution in every language.