Cargo un archivo de recursos json con el formato de texto
{ "sources": [{ "prop1": "1", "prop2": "2" }, { "prop1": "1", "prop2": "2" }, ], "redirection": [{ "prop1": "1", "prop2": "2" } ] }Tengo una clase con estas propiedades prop1 y prop2
Quiero recuperar con ObjectMapper una clase de lista. ¿Cuál es el método?
Este código no funciona....
Map<String, Object> mp = mapper.readValue(jsonResource.getInputStream(),new TypeReference<Map<String, Object>>() {}); String sourceText= new ObjectMapper().readTree(jsonResource.getInputStream()).get("sources").asText(); mapper.readValue(sourceText, new TypeReference<List<MyClass>>(){});Gracias por tu ayuda
En su caso, escribiría un JsonDeserializer personalizado. Realmente no he probado el código, pero creo que la idea es clara:
final MyClassDeserializer myClassDeserializer = new MyClassDeserializer(); final SimpleModule deserializerModule = new SimpleModule(); deserializerModule.addDeserializer(MyClass.class, myClassDeserializer); final ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(deserializerModule); Y el código para JsonDeserializer :
public class MyClassDeserializer extends JsonDeserializer<MyClass> { @Override public MyClass deserialize(final JsonParser jsonParser, final DeserializationContext context) throws IOException { final JsonNode node = jsonParser.getCodec().readTree(jsonParser); final JsonNode sourcesNode = node.get("sources"); if(node.isArray()) { final ArrayNode arrayNode = (ArrayNode) node; final Iterable<JsonNode> nodes = arrayNode::elements; final Set<Source> set = StreamSupport.stream(nodes.spliterator(), false) .map(mapper) .collect(Collectors.toSet()); ... } ... }Lo primero: su JSON no es válido. Hay una coma después del segundo objeto en la matriz de sources . Esto tiene que ser borrado.
Segundo: creo que no eligió el tipo correcto para su resultado. Lo que representa su JSON es un mapa que se asigna desde una cadena a una matriz de objetos. Entonces, el tipo debería ser algo así como Map<String, Props[]> (Dado que no proporcionó el nombre de su clase, lo llamé Props .
Con estas consideraciones, puede construir un MapType usando el método getTypeFactory() de ObjectMapper y deserializar el valor usando el tipo construido como se muestra a continuación.
ObjectMapper mapper = new ObjectMapper(); TypeFactory typeFactory = mapper.getTypeFactory(); MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, Props[].class); Map<String, Props[]> map = mapper.readValue(s, mapType);De hecho, voté por la otra respuesta, pero esta es mi idea, crear las clases y dejar que jackson haga el trabajo:
public class ResourceTest { @Test public void test1() throws IOException { assertTrue(true); Resource resource = new Resource(); resource.getRedirectrions().add(makeRedirectrion("rprop11", "rprop12")); resource.getRedirectrions().add(makeRedirectrion("rprop21", "rprop22")); resource.getSources().add(makeSource("sprop11","sprop12")); resource.getSources().add(makeSource("sprop21","sprop22")); String json = new ObjectMapper().writeValueAsString(resource); System.out.println(json); Resource resource1 = new ObjectMapper().readValue(json, Resource.class); System.out.println(resource1); } private Source makeSource(String prop1, String prop2) { Source source = new Source(); source.setProp1(prop1); source.setProp2(prop2); return source; } private Redirectrion makeRedirectrion(String prop1, String prop2) { Redirectrion redirectrion = new Redirectrion(); redirectrion.setProp1(prop1); redirectrion.setProp2(prop2); return redirectrion; } }La salida es:
{"sources":[{"prop1":"sprop11","prop2":"sprop12"},{"prop1":"sprop21","prop2":"sprop22"}],"redirectrions":[{"prop1":"rprop11","prop2":"rprop12"},{"prop1":"rprop21","prop2":"rprop22"}]} Resource{sources=[Source{prop1='sprop11', prop2='sprop12'}, Source{prop1='sprop21', prop2='sprop22'}], redirectrions=[Source{prop1='rprop11', prop2='rprop12'}, Source{prop1='rprop21', prop2='rprop22'}]}