2015-10-05 62 views
1

我想創建一個@JsonDeserializer,它可以跨類使用。我正在使用JAX-RS,並且傳入的json字符串在蛇情況下會有字段。我想覆蓋json反序列化,以便我的java對象沒有蛇狀字段。由於java對象的創建是在JAX-RS內部發生的,因此我在所有請求類中都使用了@JsonDeserializer註釋。我目前的實現有一個通用基類,但我需要擴展它所有的具體類,以便我可以傳入我想創建的實際類。有沒有辦法更一般地做到這一點?Json反序列化器,在java中的不同類中工作

例如,我有多個請求的對象是這樣的:

@JsonDeserialize(using = MyRequestDeserializer.class) 
    public class MyRequest { 
    .... 
    } 

我創建了一個通用的解串器,像這樣:

public class GenericRequestDeserializer extends JsonDeserializer<Object> { 

private static ObjectMapper objectMapper = new ObjectMapper(); 

@Override 
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 
    return null; 
} 

protected Object deserializeIt(JsonParser jsonParser, Class cls) { 
    try { 
     JsonNode node = jsonParser.getCodec().readTree(jsonParser); 
     Iterator<String> fieldNames = node.fieldNames(); 

     Object object = cls.newInstance(); 

     while(fieldNames.hasNext()) { 
      String fieldName = fieldNames.next(); 
      JsonNode value = node.get(fieldName); 

      String newFieldName = convertFieldName(fieldName); 

      //TODO: currently failing if I do not find a field, should the exception be swallowed? 
      Class returnType = object.getClass().getMethod("get" + newFieldName).getReturnType(); 
      Method setMethod = object.getClass().getMethod("set" + newFieldName, returnType); 

      Object valueToSet = null; 
      if(value.isTextual()) { 
       valueToSet = value.asText(); 
      } else if(value.isContainerNode()) { 
       valueToSet = objectMapper.readValue(value.toString(), returnType); 
      } else if (value.isInt()) { 
       valueToSet = value.asInt(); 
      } 

      setMethod.invoke(object, valueToSet); 
     } 

     return object; 

    } catch (Exception e) { 
     throw new TokenizationException(GatewayConstants.STATUS_SYSTEM_ERROR, 
       "Error in deserializeIt for " + cls.getSimpleName() + " caused by " + e.getMessage(), e); 
    } 
} 

private String convertFieldName(String fieldName) { 

    StringBuilder newFieldName = new StringBuilder(); 

    int length = fieldName.length(); 
    boolean capitalize = true; //first character should be capitalized 

    for(int i = 0; i < length; i++) { 
     char current = fieldName.charAt(i); 

     if(current == '_') { 
      //remove the underscore and capitalize the next character in line 
      capitalize = true; 
     } else if(capitalize) { 
      newFieldName.append(Character.toUpperCase(current)); 
      capitalize = false; 
     } else { 
      newFieldName.append(current); 
     } 
    } 

    return newFieldName.toString(); 
} 

}

但我仍然需要創建一個每個請求的新類以便通過適當的類創建:

public class MyRequestDeserializer extends GenericRequestDeserializer { 
@Override 
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 
    return deserializeIt(jsonParser, MyRequest.class); 
} 
} 

有什麼辦法擺脫所有MyRequestDeserializer類?換句話說,GenericRequestDeserializer能夠找出它實際上是反序列化的類嗎?

回答

0

所以我發現了一個更好的選項,用於將所有對象更改爲蛇殼。我沒有在每個類上使用Serializer和Deserializers,而是在Spring中將一個ObjectMapper注入到JsonProvider中。 ObjectMapper已經支持一個屬性,該屬性將自動處理駝峯案例。我只需要覆蓋我的類中的getSingletons方法,它擴展了Application,如下所示:

public class MyApp extends Application { 
.... 
@Override 
public Set<Object> getSingletons() { 
    final Set<Object> objects = new LinkedHashSet<Object>(); 


    ObjectMapper objectMapper = new ObjectMapper(); 
    objectMapper.setPropertyNamingStrategy(
      PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); 

    objects.add(new JacksonJsonProvider(objectMapper)); 

    return objects; 
} 
}