Reputation: 329
I want to convert JSON to a HashMap with Jackson. This is my JSON:
String json = "[{\"Opleidingen\":[{\"name\":\"Bijz. trajecten zorg en welzijn\",\"afk\":\"BTZW\",\"id\":\"0\"},{\"name\":\"Bouwkunde\",\"afk\":\"Bwk\",\"id\":\"14\"},{\"name\":\"Electrotechniek / mechatronica\",\"afk\":\"EltMe\",\"id\":\"15\"},{\"name\":\"Extern\",\"afk\":\"Extern\",\"id\":\"16\"},{\"name\":\"Gezondheidszorg\",\"afk\":\"Zorg\",\"id\":\"17\"},{\"name\":\"Handel\",\"afk\":\"Hand\",\"id\":\"18\"},{\"name\":\"Horeca\",\"afk\":\"Hor\",\"id\":\"19\"},{\"name\":\"Ict\",\"afk\":\"ICT\",\"id\":\"20\"},{\"name\":\"Maatschappelijke zorg\",\"afk\":\"MZ\",\"id\":\"21\"},{\"name\":\"Onderwijs assistent / pedagogisch werk\",\"afk\":\"OAPW\",\"id\":\"22\"},{\"name\":\"Tab / brug\",\"afk\":\"TAB\",\"id\":\"23\"},{\"name\":\"Werktuigbouw / maritieme techniek\",\"afk\":\"WtbMt\",\"id\":\"24\"},{\"name\":\"Zakelijke dienstverlening\",\"afk\":\"TAB\",\"id\":\"25\"}]},{\"Klassen\":[{\"name\":\"V2ZWA\",\"cat\":\"BTZW\",\"id\":\"1\"},{\"name\":\"V2ZWB\",\"cat\":\"Bwk\",\"id\":\"2\"},{\"name\":\"V2ZWB\",\"cat\":\"BTZW\",\"id\":\"3\"},{\"name\":\"V3B2A\",\"cat\":\"BTZW\",\"id\":\"3\"},{\"name\":\"V3B2B\",\"cat\":\"BTZW\",\"id\":\"4\"},{\"name\":\"V3B2C\",\"cat\":\"BTZW\",\"id\":\"5\"},{\"name\":\"V3B2D\",\"cat\":\"BTZW\",\"id\":\"6\"},{\"name\":\"V3B2E\",\"cat\":\"BTZW\",\"id\":\"7\"},{\"name\":\"V3B3A\",\"cat\":\"BTZW\",\"id\":\"8\"},{\"name\":\"V3B3B\",\"cat\":\"BTZW\",\"id\":\"9\"},{\"name\":\"V3B3C\",\"cat\":\"BTZW\",\"id\":\"10\"},{\"name\":\"VWA\",\"cat\":\"BTZW\",\"id\":\"11\"},{\"name\":\"VWB\",\"cat\":\"BTZW\",\"id\":\"12\"},{\"name\":\"VWC\",\"cat\":\"BTZW\",\"id\":\"13\"}]}]";
I want that I fill in the ID that I get the name back, so: result.get("13");
returns VWC
and result.get("0");
returns Bijz. trajecten zorg en welzijn
.
I've tried this:
try {
@SuppressWarnings("unchecked")
ArrayList<LinkedHashMap<?, ?>> result = new ObjectMapper().readValue(json, ArrayList.class);
System.out.println(result.get(1).get("id"));
} catch (JsonParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JsonMappingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But then this is the content of result.get(1);
:
I/System.out(809): {Klassen=[{name=V2ZWA, cat=BTZW, id=1}, {name=V2ZWB, cat=Bwk, id=2}, {name=V2ZWB, cat=BTZW, id=3}, {name=V3B2A, cat=BTZW, id=3}, {name=V3B2B, cat=BTZW, id=4}, {name=V3B2C, cat=BTZW, id=5}, {name=V3B2D, cat=BTZW, id=6}, {name=V3B2E, cat=BTZW, id=7}, {name=V3B3A, cat=BTZW, id=8}, {name=V3B3B, cat=BTZW, id=9}, {name=V3B3C, cat=BTZW, id=10}, {name=VWA, cat=BTZW, id=11}, {name=VWB, cat=BTZW, id=12}, {name=VWC, cat=BTZW, id=13}]}
Also I've tried it without Jackson:
for (int i = 0; i < jObject.length(); i++) {
JSONArray opleidingen = jObject.getJSONObject(i).getJSONArray("Opleidingen");
for (int i2 = 0; i2 < opleidingen.length(); i2++) {
outMap.put(opleidingen.getJSONObject(i2).getString("id"), opleidingen.getJSONObject(i2).getString("name"));
}
JSONArray klassen = jObject.getJSONObject(i).getJSONArray("Klassen");
for (int i3 = 0; i3 < klassen.length(); i3++) {
outMap.put(klassen.getJSONObject(i3).getString("id"), klassen.getJSONObject(i3).getString("name"));
}
}
But that is neither working.
Is it possible to convert my JSON to a HashMap (and when ID is given that it returns the name)?
(ArrayList class can be found here)
Upvotes: 2
Views: 5410
Reputation: 38710
I think, you should separate deserialization logic from the way how to retrieve names at the end. For deserialization use as simle method as you can. For example, you can create POJO classes which describe your JSON. See below example. POJO classes:
class EntitiesOwner {
private String name;
private List<Entity> entities;
@JsonAnySetter
public void setProperties(String name, List<Entity> entities) {
this.name = name;
this.entities = entities;
}
public String getName() {
return name;
}
public List<Entity> getEntities() {
return entities;
}
@Override
public String toString() {
return "EntitiesOwner [name=" + name + ", entities=" + entities + "]";
}
}
class Entity {
private int id;
private String afk;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAfk() {
return afk;
}
public void setAfk(String afk) {
this.afk = afk;
}
public void setCat(String cat) {
this.afk = cat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Entity [id=" + id + ", afk=" + afk + ", name=" + name + "]";
}
}
Now you can easily deserialize it in this way:
ObjectMapper mapper = new ObjectMapper();
EntitiesOwner[] owners = mapper.readValue(json, EntitiesOwner[].class);
System.out.println(Arrays.toString(owners));
Above program prints:
[EntitiesOwner [name=Opleidingen, entities=[Entity [id=0, afk=BTZW, name=Bijz. trajecten zorg en welzijn], Entity [id=14, afk=Bwk, name=Bouwkunde], Entity [id=15, afk=EltMe, name=Electrotechniek / mechatronica], Entity [id=16, afk=Extern, name=Extern], Entity [id=17, afk=Zorg, name=Gezondheidszorg], Entity [id=18, afk=Hand, name=Handel], Entity [id=19, afk=Hor, name=Horeca], Entity [id=20, afk=ICT, name=Ict], Entity [id=21, afk=MZ, name=Maatschappelijke zorg], Entity [id=22, afk=OAPW, name=Onderwijs assistent / pedagogisch werk], Entity [id=23, afk=TAB, name=Tab / brug], Entity [id=24, afk=WtbMt, name=Werktuigbouw / maritieme techniek], Entity [id=25, afk=TAB, name=Zakelijke dienstverlening]]], EntitiesOwner [name=Klassen, entities=[Entity [id=1, afk=BTZW, name=V2ZWA], Entity [id=2, afk=Bwk, name=V2ZWB], Entity [id=3, afk=BTZW, name=V2ZWB], Entity [id=3, afk=BTZW, name=V3B2A], Entity [id=4, afk=BTZW, name=V3B2B], Entity [id=5, afk=BTZW, name=V3B2C], Entity [id=6, afk=BTZW, name=V3B2D], Entity [id=7, afk=BTZW, name=V3B2E], Entity [id=8, afk=BTZW, name=V3B3A], Entity [id=9, afk=BTZW, name=V3B3B], Entity [id=10, afk=BTZW, name=V3B3C], Entity [id=11, afk=BTZW, name=VWA], Entity [id=12, afk=BTZW, name=VWB], Entity [id=13, afk=BTZW, name=VWC]]]]
For resolving entities I propose to create new class which can help you with this. For example:
class EntityResolver {
private Map<Integer, Entity> entities;
public EntityResolver(EntitiesOwner[] owners) {
entities = new HashMap<Integer, Entity>(owners.length);
for (EntitiesOwner owner : owners) {
for (Entity entity : owner.getEntities()) {
entities.put(entity.getId(), entity);
}
}
}
public Entity getById(int id) {
return entities.get(id);
}
}
Simple usage:
EntityResolver resolver = new EntityResolver(owners);
System.out.println(resolver.getById(0).getName());
System.out.println(resolver.getById(13).getName());
Above program prints:
Bijz. trajecten zorg en welzijn
VWC
Upvotes: 2
Reputation: 13187
By default, a list in JSON maps to an ArrayList in Java. There might be a way to deserialize the list to a HashMap directly, but even then that method would be very complicated. Why not just deserialize your JSON list to an ArrayList and do some post processing to obtain the HashMap? Something like this:
public Map<Integer, String> listToMap(List<Object> list) {
Map<Integer, String> map = new HashMap<>();
for (Object obj : list) {
// you might want to try-catch all casts, some data might be invalid
Map<String, Object> elt = (Map<String, Object>) obj;
Integer id = (Integer) elt.get("id");
String name = (String) elt.get("name");
map.put(id, name);
}
return map;
}
EDIT
I didn't make explicit how to obtain the list to feed to the method above. In the snippet below, I use the String json
like you declared it in your question. For completeness, refer to the raw data binding from the Jackson documentation.
List<Object> inputData = new ObjectMapper().readValue(json, List.class);
Map<String, Object> inputMap = (Map<String, Object>) inputData.get(0);
List<Object> opleidingen = (List<Object>) inputMap.get("Opleidingen");
List<Object> klassen = (List<Object>) inputMap.get("Klassen");
Map<Integer, String> opleidingenMap = listToMap(opleidingen);
Map<Integer, String> klassenMap = listToMap(klassen);
Now you can use the two maps in the way you described:
opleidingenMap.get(25)
gives
"Zakelijke dienstverlening"
Note that this way you end up with a separate map for opleidingen and klassen. If you'd rather have all elements in one map, you could make such a map like:
Map<Integer, String> fullMap = new HashMap<>();
fullMap.putAll(opleidingenMap);
fullMap.putAll(klassen);
Note that this assumes that there is no opleiding with the same id as some klas.
Upvotes: 0