2015-06-09 17 views
8

voglio convertire JSON tramite biblioteca Jackson a una mappa contenente chiave camelCase ... diciamo ...Jackson JSON per mappare e CamelCase nome della chiave

da

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

a questo. ..

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

My Code ...

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>>(){}); 
} 

Ma questo non funziona ... anche altri propertyNamingStrategy non funziona su JSON ... come ...

{ 
    "someKey": "SomeValue" 
} 

mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.PascalCaseStrategy()) 

a

{ 
    "SomeKey": "SomeValue" 
} 

Come ottenere il nome della chiave CamelCase Map tramite jackson ... o dovrei eseguire il loop manuale della mappa e convertire la chiave o ci sono altri modi ???

Grazie in anticipo ...

+1

Questo guarda le linee di quello che stai cercando di ottenere: https: // github.com/FasterXML/jackson-databind/issues/62 –

risposta

6

Come si lavora con mappe/dizionari, invece di legare i dati JSON a POJO (classi Java esplicite che corrispondono ai dati JSON), la strategia di denominazione di proprietà non si applica:

Classe PropertyNamingStrategy ... definisce come nomi delle proprietà JSON ("nomi esterni") sono derivati ​​da nomi di metodi POJO e campi ("nomi interni")

Pertanto, è necessario prima analizzare i dati utilizzando Jackson e quindi iterare sul risultato e convertire le chiavi.

modificare il codice in questo modo:

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

e aggiungere questi metodi:

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

Mille grazie per aver dedicato del tempo e notare che c'era un problema nella strategia di denominazione delle proprietà che non si applicava agli oggetti non POJO. Sto lavorando a un progetto legacy, quindi cambiare le mappe di POJO non era un'opzione. Tuttavia, i metodi proposti sono stati davvero utili e sono riuscito a ottenere la mappatura corretta apportando alcune modifiche. – dic19

+0

Questo mi ha salvato la vita. Pensavo di fare qualcosa di sbagliato! BTW Guava 'CaseFormat' è molto utile per la conversione String invece di riscrivere mapKey. https://github.com/google/guava/wiki/StringsExplained#caseformat –

3

È sempre possibile scandire le chiavi della mappa e aggiornarli. Tuttavia, se sei interessato solo a produrre un JSON con chiavi del caso cammello, potresti considerare l'approccio descritto di seguito.

Si potrebbe avere un serializzatore di chiave personalizzato. Sarà usato durante la serializzazione un'istanza Map a 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); 
    } 
} 

Poi fare come seguendo:

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

L'output sarà:

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

Con questo approccio, i tasti di il Map non sarà nel caso cammello. Ma ti darà l'output desiderato.

Problemi correlati