Consumidor JSON de objetos polimórficos

Estoy analizando JSON y estoy teniendo dificultades con una estructura que puede tener una de tres formas. En mi caso, podría ser cero-dimensional, unidimensional o bidimensional. ¿Hay alguna manera de que pueda inspeccionar el JSON sobre la marcha para determinar cuál es? O tal vez consumirlo de todos modos y averiguar qué es después.

Las estructuras se ven así y pueden integrarse en otras estructuras.

"details":{ "Product":"A zero-dimensional Product" }, "details":{ "Product":"A one-dimensional Product", "Dimensions": [ "Size" ], "Labels": [ "XS", "S", "M", "L" ] }, "details":{ "Product":"A two-dimensional Product", "Dimensions": [ "Size", "Fit" ], "Labels": [[ "XS", "S", "M", "L" ],[ "26", "28", "30", "32" ]] } 

Lo que podría estar buscando es una clase genérica con la que Jackson siempre coincidirá.

Algo como traducir:

 { "SomeField": "SomeValue", ... "details":{ ... } } 

Dentro:

 class MyClass { String SomeField; ... AClass details; } 

¿Existe una clase AClass que pueda definir que pueda ser un destinatario universal para cualquier estructura o matriz JSON?

Gracias al comentario de Eric que me señalaba Programmerbruce logré descifrarlo. Aquí está el código que utilicé (recorte para simplificar).

 public static class Info { @JsonProperty("Product") public String product; // Empty in the 0d version, One entry in the 1d version, two entries in the 2d version. @JsonProperty("Dimensions") public String[] dimensions; } public static class Info0d extends Info { } public static class Info1d extends Info { @JsonProperty("Labels") public String[] labels; } public static class Info2d extends Info { @JsonProperty("Labels") public String[][] labels; } public static class InfoDeserializer extends StdDeserializer { public InfoDeserializer() { super(Info.class); } @Override public Info deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { Class< ? extends Info> variantInfoClass = null; ObjectMapper mapper = (ObjectMapper) jp.getCodec(); ObjectNode root = (ObjectNode) mapper.readTree(jp); // Inspect the `diemnsions` field to decide what to expect. JsonNode dimensions = root.get("Dimensions"); if ( dimensions == null ) { variantInfoClass = Info0d.class; } else { switch ( dimensions.size() ) { case 1: variantInfoClass = Info1d.class; break; case 2: variantInfoClass = Info2d.class; break; } } if (variantInfoClass == null) { return null; } return mapper.readValue(root, variantInfoClass); } } 

Y para instalar esto en ObjectMapper :

 // Register the special deserializer. InfoDeserializer deserializer = new InfoDeserializer(); SimpleModule module = new SimpleModule("PolymorphicInfoDeserializerModule", new Version(1, 0, 0, null)); module.addDeserializer(Info.class, deserializer); mapper.registerModule(module); factory = new JsonFactory(mapper); 

¿Es esta estructura lo que quieres para AClass?

 class Dimension { String name; List possibleValues; } class Product { String name; List dimensions; } 

Todo lo que necesita hacer es cambiar la longitud de la lista de dimensions para tener en cuenta los tres tipos.

El análisis se convierte en un problema trivial al verificar si la propiedad Dimensions está presente en el JSON y, de ser así, iterar sobre ella y anexarla a la lista de dimensions .


Otra idea sería reestructurar el JSON (si puede) de manera que todos los casos sean de la misma forma:

 "d0":{ "Product":"A zero-dimensional Product", "Dimensions": {} }, "d1":{ "Product":"A one-dimensional Product", "Dimensions": { "Size": [ "XS", "S", "M", "L" ] } }, "d2":{ "Product":"A two-dimensional Product", "Dimensions": { "Size": [ "XS", "S", "M", "L" ], "Fit": [ "26", "28", "30", "32" ] } }