1

Considering the following JSON :

[
  {
    "map": "TEST",
    "values": [
      "test",
      "test2"
    ]
  },
  {
    "map": "TEST1",
    "values": [
      "test",
      "test3",
      "test4"
    ]
  },
  {
    "map": "TEST2",
    "values": [
      "test4",
      "test2",
      "test5",
      "test2"
    ]
  }
]

which have been loaded into a string by the getResourceAsString function. How can I make a HashMap where my key is "map" field, and my value is an array of "values" field ? I tried many solutions in other similar questions, but nothing worked.

Here is the beginning of my code :

    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

But I don't know how to assign it to a Map, readValue method doesn't seems to give the right thing

faceID
  • 81
  • 7
  • 1
    Why not just parse it as a list of maps and then transform that into a single map? – ernest_k Oct 28 '19 at 10:59
  • How to achieve this ? When I try to assign it to a list of maps, I get out of array exceptions Type mapType = new TypeToken>(){}.getType(); Map son = new Gson().fromJson(str, mapType); -> Expected BEGIN_ARRAY but was BEGIN_OBJECT – faceID Oct 28 '19 at 11:11
  • Possible duplicate of [Convert JSON to Map](https://stackoverflow.com/questions/443499/convert-json-to-map) – Kirill Oct 28 '19 at 11:16

3 Answers3

2

You can deserialise it to List<Map<String, Object>> and later transform to Map:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./src/main/resources/test.json");

        ObjectMapper mapper = new ObjectMapper();

        TypeReference rootType = new TypeReference<List<Map<String, Object>>>() { };
        List<Map<String, Object>> root = mapper.readValue(jsonFile, rootType);
        Map<String, Object> result = root.stream()
                 .collect(Collectors.toMap(
                         m -> m.get("map").toString(),
                         m -> m.get("values")));
        System.out.println(result);
    }
}

Above code prints:

{TEST2=[test4, test2, test5, test2], TEST=[test, test2], TEST1=[test, test3, test4]}
Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • 1
    I'd vote for this as the use of TypeReference is makes for a type-safe and readable solution. However, Stream.reduce() is not intended for use with mutable data types - this is what Stream.collect() is for! – drekbour Oct 28 '19 at 12:48
  • @drekbour, of course you are right. `collect` fits better here. – Michał Ziober Oct 28 '19 at 13:54
0

You can use List<Map<Object,Object>> for this json as it as list of 3 objects, so it cannot be directly casted to a HashMap, so try this:

String json = "[{\"map\":\"TEST\",\"values\":[\"test\",\"test2\"]},{\"map\":\"TEST1\",\"values\":[\"test\",\"test3\",\"test4\"]},{\"map\":\"TEST2\",\"values\":[\"test4\",\"test2\",\"test5\",\"test2\"]}]";

List<Map<Object, Object>> jsonObj = mapper.readValue(json, List.class);
Mustahsan
  • 3,852
  • 1
  • 18
  • 34
0

You can do it like this:

ArrayNode rootNode = (ArrayNode) new ObjectMapper().readTree(...);
Map<String, List<String>> map = new LinkedHashMap<>();
for (int i = 0; i < rootNode.size(); i++) {
    JsonNode objNode = rootNode.get(i);
    String name = objNode.get("map").textValue();
    ArrayNode valuesNode = (ArrayNode) objNode.get("values");
    List<String> values = new ArrayList<>(valuesNode.size());
    for (int j = 0; j < valuesNode.size(); j++)
        values.add(valuesNode.get(j).textValue());
    map.put(name, values);
}

Result

{TEST=[test, test2], TEST1=[test, test3, test4], TEST2=[test4, test2, test5, test2]}
Andreas
  • 154,647
  • 11
  • 152
  • 247