Search code examples
javajsonjacksonobjectmapper

Convert JSON record to LinkedHashMap<String,String> using Jackson API


I have a JSON file(it contains an array of JSON objects.) I am trying to read it object by object. Each object I need to convert it to a LinkedHashMap<String,String> where both the key and value are strings. Note that even if the JSON objects contain a non-string value(Integer/Boolean), I want my LinkedHashMap to contain a string.

This is my JSON file (films.json):

[
  {
    "name": "Fight Club",
    "year": 1999,
  }
]

Now, this has 1 object. I want to convert it to a LinkedHashMap<String,String>.

So for the above example, my LinkedHashMap should contain(for the 1st JSON object) :

"name" : "Fight CLub"

"year" : "1999"

Notice how the year is String in the LinkedHashMap and not Integer.

This is what I tried.

Map<String, Object> myLinkedHashMap;

JsonParser jsonParser = new JsonFactory().createParser(new File("films.json"));
jsonParser = new JsonFactory().createParser(new File(filePath));
jsonParser.nextToken();

ObjectMapper  mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

while(jsonParser.nextToken() != JsonToken.END_ARRAY){
    myLinkedHashMap  = mapper.readValue(jsonParser, LinkedHashMap.class);
}

The variable myLinkedHashMap will contain a key/value pair for an object in my JSON file.

But the problem is that for 'year' of the JSON file, I am getting Integer in the LinkedHashMap as the JSON file also contains Integer.

Instead, I want the Integer as String in the LinkedHashMap.

Please help me get String in the LinkedHashMap instead of Integer.

Note: The solution should be generic to other data types also.

So if the JSON object contains boolean true, then my LinkedHashMap should contain "true".


Solution

  • You can construct map type using TypeFactory and constructMapType method to tell exactly what do you need from readValue method. See below example:

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.JsonToken;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.type.MapType;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.springframework.util.Assert;
    
    import java.io.File;
    import java.util.LinkedHashMap;
    
    public class JsonMapApp {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./resource/test.json").getAbsoluteFile();
    
            ObjectMapper mapper = new ObjectMapper();
            mapper.registerModule(new JavaTimeModule());
            mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    
            JsonParser jsonParser = mapper.getFactory().createParser(jsonFile);
            jsonParser.nextToken();
    
            MapType mapType = mapper.getTypeFactory().constructMapType(LinkedHashMap.class, String.class, String.class);
            while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
                LinkedHashMap<String, String> map = mapper.readValue(jsonParser, mapType);
                map.forEach((k, v) -> {
                    Assert.isInstanceOf(String.class, v);
                    System.out.println(k + " -> " + v + " (" + v.getClass().getName() + ")");
                });
            }
        }
    }
    

    Above code prints:

    name -> Fight Club (java.lang.String)
    year -> 1999 (java.lang.String)