2015-06-09 3 views
8

Я хочу, чтобы преобразовать JSON на карту, содержащую верблюжий ключ ... скажем через библиотеку Джексона ...Jackson JSON на карту и CamelCase имя ключа

из

{ 
    "SomeKey": "SomeValue", 
    "AnotherKey": "another value", 
    "InnerJson" : {"TheKey" : "TheValue"} 
} 

к этому. ..

{ 
    "someKey": "SomeValue", 
    "anotherKey": "another value", 
    "innerJson" : {"theKey" : "TheValue"} 
} 

мой код ...

public Map<String, Object> jsonToMap(String jsonString) throws IOException 
{ 
    ObjectMapper mapper=new ObjectMapper(); 
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
    return mapper.readValue(jsonString,new TypeReference<Map<String, Object>>(){}); 
} 

Но это не работает ... даже другой propertyNamingStrategy не работает ... JSON, такие как ...

{ 
    "someKey": "SomeValue" 
} 

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy()) 

в

{ 
    "SomeKey": "SomeValue" 
} 

Как получить имя ключа camelCase Map через jackson ... или я должен вручную отобразить карту и преобразовать ключ, или есть какой-то другой способ ???

Заранее спасибо ...

+1

Это выглядит так, как вы пытаетесь достичь: https: // github.com/FasterXML/jackson-databind/issues/62 –

ответ

6

Как вы работаете с картами/словарями вместо привязки данных в формате JSON для POJOs (явные Java-классы, которые соответствуют данным в формате JSON), стратегия именования свойства не применяется:

Класс PropertyNamingStrategy ... определяет, как имена свойств JSON ("внешние имена") являются производными от имен методов POJO и полей ("внутренние имена")

Поэтому вы должны сначала проанализировать данные с помощью Jackson, а затем перебрать результат и преобразовать ключи.

Изменить код так:

public Map<String, Object> jsonToMap(String jsonString) throws IOException 
{ 
    ObjectMapper mapper=new ObjectMapper(); 
    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
    Map<String, Object> map = mapper.readValue(jsonString,new TypeReference<Map<String, Object>>(){}); 
    return convertMap(map); 
} 

И добавить эти методы:

public String mapKey(String key) { 
    return Character.toLowerCase(key.charAt(0)) + key.substring(1); 
} 

public Map<String, Object> convertMap(Map<String, Object> map) { 
    Map<String, Object> result = new HashMap<String, Object>(); 
    for (Map.Entry<String, Object> entry : map.entrySet()) { 
     String key = entry.getKey(); 
     Object value = entry.getValue(); 
     result.put(mapKey(key), convertValue(value)); 
    } 
    return result; 
} 

public convertList(Lst<Object> list) { 
    List<Object> result = new ArrayList<Object>(); 
    for (Object obj : list) { 
     result.add(convertValue(obj)); 
    } 
    return result; 
} 

public Object covertValue(Object obj) { 
    if (obj instanceof Map<String, Object>) { 
     return convertMap((Map<String, Object>) obj); 
    } else if (obj instanceof List<Object>) { 
     return convertList((List<Object>) obj); 
    } else { 
     return obj; 
    } 
} 
+1

Большое спасибо за то, что нашли время и отметили, что это была проблема стратегии присвоения свойств, не применимой к объектам без POJO. Я работаю над старым проектом, поэтому изменение карт POJO не было возможным. Однако предлагаемые методы были действительно полезными, и мне удалось получить правильное отображение, выполнив несколько настроек. – dic19

+0

Это спасло мою жизнь. Я думал, что делаю что-то неправильно! BTW Guava 'CaseFormat' очень полезен для преобразования строк вместо переписывания mapKey. https://github.com/google/guava/wiki/StringsExplained#caseformat –

3

Вы всегда можете перебрать ключей карты и обновлять их. Однако, если вы заинтересованы только в создании JSON с ключами на верблюжьей кейсе, вы можете рассмотреть подход, описанный ниже.

У вас может быть собственный ключевой сериализатор. Он будет использоваться при сериализации Map экземпляра JSON:

public class CamelCaseKeySerializer extends JsonSerializer<String> { 

    @Override 
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) 
       throws IOException, JsonProcessingException { 

     String key = Character.toLowerCase(value.charAt(0)) + value.substring(1); 
     gen.writeFieldName(key); 
    } 
} 

Затем выполните следующие действия:

String json = "{\"SomeKey\":\"SomeValue\",\"AnotherKey\":\"another value\",\"InnerJson\":" 
      + "{\"TheKey\":\"TheValue\"}}"; 

SimpleModule simpleModule = new SimpleModule(); 
simpleModule.addKeySerializer(String.class, new CamelCaseKeySerializer()); 

ObjectMapper mapper = new ObjectMapper(); 
mapper.registerModule(simpleModule); 

Map<String, Object> map = mapper.readValue(json, 
              new TypeReference<Map<String, Object>>() {}); 

String camelCaseJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map); 

Выход будет:

{ 
    "someKey" : "SomeValue", 
    "anotherKey" : "another value", 
    "innerJson" : { 
    "theKey" : "TheValue" 
    } 
} 

При таком подходе ключей Map не будет в чехле для верблюда. Но это даст вам желаемый результат.

Смежные вопросы