2013-10-08 25 views
5

Data una struttura come questa:Jackson JSON chiave della mappa di propietà oggetto contenuto

{ 
    "nameOfObject": { "score": 100 }, 
    "anotherObject": { "score": 30 } 
} 

E 'possibile mappare questo a:

class Container { 
    Map<String, ScoreKeeper> scoreKeepers; 
} 

class ScoreKeeper { 
    String name; 
    int score; 
} 

In modo che si finisce con l'name proprietà di le istanze ScoreKeeper impostate su "nameOfObject" e "anotherObject", rispettivamente?

+1

si avrà probabilmente bisogno di creare una tra mediare l'oggetto su cui serializzare, che a sua volta può essere convertito nella rappresentazione desiderata. – Bart

risposta

2

Sono fermamente convinto nel separare i POJO dall'esternalizzazione. Leggi il tuo JSON in una mappa e poi costruire contenitore di oggetti/segnapunti come questo (apols per eventuali errori di battitura):

mapper = new ObjectMapper(); 

Map<String,Object> data = mapper.readValue(inputstream, Map.class); 

Container c = new Container(); 

for(Map.Entry<String, Object> me : data.entrySet()) { 
    String key = me.getKey(); 
    Map info = (Map) me.getValue(); 

    ScoreKeeper sk = new ScoreKeeper(); 
    sk.setName(key); 
    Integer q = info.get("score"); 
    sk.setScore(q); 

    c.put(key, sk); 
} 
+0

Sicuro. In realtà stavo solo cercando un modo sintetico per deserializzare un'API esistente. Grazie per il suggerimento però. –

2

soluzione alternativa, in cui la chiave name è impostato sull'oggetto valore utilizzando un Deserializer personalizzato:

@Test 
public void test() throws JsonParseException, JsonMappingException, IOException { 
    ObjectMapper mapper = new ObjectMapper(); 

    Data data = mapper.readValue("{\"users\": {\"John\": {\"id\": 20}, \"Pete\": {\"id\": 30}}}", Data.class); 

    assertEquals(20, data.users.get("John").id); 
    assertEquals(30, data.users.get("Pete").id); 
    assertEquals("John", data.users.get("John").name); 
    assertEquals("Pete", data.users.get("Pete").name); 
} 

public static class Data { 
    @JsonDeserialize(contentUsing = Deser.class) 
    public Map<String, User> users; 
} 

public static class User { 
    public String name; 
    public int id; 
} 

public static class Deser extends JsonDeserializer<User> { 

    @Override 
    public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
     String name = ctxt.getParser().getCurrentName(); 

     User user = p.readValueAs(User.class); 

     user.name = name; // This copies the key name to the value object 

     return user; 
    } 
} 
+0

Non ero in grado di far funzionare questo approccio con il JSON richiesto (nella domanda originale), questo approccio funziona solo se c'è un nodo radice contenente 'nameOfObject' e 'anotherObject' – Nick

0

Ecco una versione migliorata del @Buzz Moschetti di, utilizza di Jackson ObjectMapper.convertValue() per gestire l'analisi delle proprietà

ObjectMapper mapper = new ObjectMapper(); 

Map<String,Object> data = mapper.readValue(inputstream, Map.class); 

Container c = new Container(); 

for(Map.Entry<String, Object> entry : data.entrySet()) { 
    String name = entry.getKey(); 
    ScoreKeeper sk = mapper.convertValue(entry.getValue(), ScoreKeeper.class); 
    sk.name = name; 
    c.scoreKeepers.put(name, sk); 
} 
Problemi correlati