2017-04-21 102 views
0

我需要将标准Json数组映射到自定义List类型(实际上不是java.util.List,除了javaslang.collection.List之外)。除了复杂性之外,我们没有静态bean,我们可以将列表类型定义为javaslang类型,但我们需要映射到通用映射,但列表实例应该是javaslang.collection.List类型。Jackson自定义列表实例类型

我尝试创建新的自定义反序列化器,但由于我们试图陷入通用映射中,它根本没有触及那个自定义反序列化器。

例如,以下是我们希望通过的测试用例。

@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); 
} 

任何帮助表示赞赏。

回答

0

为Map写一个反序列化器可以得到想要的结果。事情是这样的:

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; 
    } 
} 

注:

  • 上面的代码也会解析内部对象类型包含HashMap的情况下,实现可以根据需要改变。
  • 可以添加更多的案例来处理字符串,整数等,作为那里的相应类型的实例,并且可以在需要的地方完成异常处理。上述解串器的

示例用法:

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