2017-04-21 2 views
0

Ich habe eine Standard-JSON-Array zu einem benutzerdefinierten List-Typ zuordnen (intraf nicht java.util.List auf alle außer javaslang.collection.List). Zur Komplexität hinzufügen, haben wir keine statischen Beans, in denen wir den Listentyp als javaslang-Typ definieren könnten, aber wir müssen auf generische Map abbilden, aber die Listeninstanz sollte vom Typ javaslang.collection.List sein.Jackson benutzerdefinierte Liste Instanztyp

Ich habe versucht, neue benutzerdefinierte Deserializer zu erstellen, aber da wir versuchen, in generische Map zu desertieren, berührt es diesen benutzerdefinierten Deserializer überhaupt nicht.

Zum Beispiel, hier ist der Testfall, den wir durchlaufen wollen.

@Test 
@DisplayName("list instance is javaslang list") 
void listAsJsList() throws Exception { 
    Map<String, Object> object = objectMapper.readValue(
      "{\"records\": [{\"id\": \"123\"}, {\"id\": \"124\"} ] }", HashMap.class); 
    assertThat(object.get("records")).isInstanceOf(javaslang.collection.List.class); 
} 

Jede Hilfe wird geschätzt.

Antwort

0

Das Schreiben eines Deserialisierers für Map kann zu den gewünschten Ergebnissen führen. Etwas wie folgt aus:

class MapDeserializer extends JsonDeserializer<Map<String, Object>> { 

    @Override 
    public Map<String, Object> deserialize(JsonParser paramJsonParser, DeserializationContext paramDeserializationContext) 
      throws IOException, JsonProcessingException { 
     JsonNode node = paramJsonParser.getCodec().readTree(paramJsonParser); 
     return parseObject(node); 
    } 

    private Map<String, Object> parseObject(JsonNode node) { 
     Map<String, Object> object = new HashMap<String, Object>(); 
     Iterator<Map.Entry<String, JsonNode>> itr = node.fields(); 
     while (itr.hasNext()) { 
      Map.Entry<String, JsonNode> entry = itr.next(); 
      if (entry.getValue().isArray()) 
       object.put(entry.getKey(), parseArray(entry.getValue())); 
      else if (entry.getValue().isObject()) 
       object.put(entry.getKey(), parseObject(entry.getValue())); 
      else 
       object.put(entry.getKey(), entry.getValue().asText()); 
     } 
     return object; 
    } 

    private List<Object> parseArray(JsonNode node) { 
     List<Object> list = List.of(); 
     Iterator<JsonNode> itr = node.elements(); 
     while (itr.hasNext()) { 
      JsonNode currentNode = itr.next(); 
      if (currentNode.isObject()) 
       list = list.prepend(parseObject(currentNode)); 
      else if (currentNode.isArray()) 
       list = list.prepend(parseArray(currentNode)); 
      else 
       list = list.prepend(currentNode.asText()); 
     } 
     return list; 
    } 
} 

Hinweis:

  • Above Code interne Objekte analysieren auch Instanz vom Typ Hashmaps kann Implementierung bei Bedarf geändert werden.
  • Weitere Fälle können hinzugefügt werden, um String, Integer usw. zu behandeln, da die Instanz der jeweiligen Typen und die Ausnahmebehandlung dort durchgeführt werden kann, wo sie benötigt wird.

Verwendungsbeispiel von oben Deserializer:

ObjectMapper mapper = new ObjectMapper(); 
SimpleModule module = new SimpleModule(); 
module.addDeserializer(Map.class, new MapDeserializer()); 
mapper.registerModule(module); 
Map<String, Object> result = mapper.readValue("{\"records\": [{\"id\": \"123\"}, {\"id\": \"124\"} ] }", Map.class); 
if (result.get("records") instanceof javaslang.collection.List) { 
    System.out.println("records are of type javaslang list"); 
} 
// Prints: records are of type javaslang list 
Verwandte Themen