85

I have a JSONObject with some attributes that I want to convert into a Map<String, Object>

Is there something that I can use from the json.org or ObjectMapper?

Marco C
  • 3,101
  • 3
  • 30
  • 49

10 Answers10

52

You can use Gson() (com.google.gson) library if you find any difficulty using Jackson.

//changed yourJsonObject.toString() to yourJsonObject as suggested by Martin Meeser

HashMap<String, Object> yourHashMap = new Gson().fromJson(yourJsonObject, HashMap.class);
Manoranjan
  • 985
  • 10
  • 14
44

use Jackson (https://github.com/FasterXML/jackson) from http://json.org/

HashMap<String,Object> result =
       new ObjectMapper().readValue(<JSON_OBJECT>, HashMap.class);
Jeroen Steenbeeke
  • 3,884
  • 5
  • 17
  • 26
A Paul
  • 8,113
  • 3
  • 31
  • 61
  • 2
    @MarcoCalì If you're using Jackson you wouldn't **need** to use a `JSONObject` and this does exactly what you're asking to do. – Brian Roach Feb 04 '14 at 06:11
  • 1
    It's been removed Also any way of LinkedHashMap? – A_rmas Jun 17 '16 at 04:07
  • As far as I can see, @Manoranjan's answer is the only correct one here, even though going via string serialization and back to a map via GSON doesn't seem ideal. It's unfortunate that JSONObject can take a Map as input but not produce one as output. – JHH Nov 28 '19 at 14:18
33

This is what worked for me:

    public static Map<String, Object> toMap(JSONObject jsonobj)  throws JSONException {
        Map<String, Object> map = new HashMap<String, Object>();
        Iterator<String> keys = jsonobj.keys();
        while(keys.hasNext()) {
            String key = keys.next();
            Object value = jsonobj.get(key);
            if (value instanceof JSONArray) {
                value = toList((JSONArray) value);
            } else if (value instanceof JSONObject) {
                value = toMap((JSONObject) value);
            }   
            map.put(key, value);
        }   return map;
    }

    public static List<Object> toList(JSONArray array) throws JSONException {
        List<Object> list = new ArrayList<Object>();
        for(int i = 0; i < array.length(); i++) {
            Object value = array.get(i);
            if (value instanceof JSONArray) {
                value = toList((JSONArray) value);
            }
            else if (value instanceof JSONObject) {
                value = toMap((JSONObject) value);
            }
            list.add(value);
        }   return list;
}

Most of this is from this question: How to convert JSONObject to new Map for all its keys using iterator java

NSchorr
  • 875
  • 10
  • 13
10

The JSONObject has a method toMap which returns Map<String,Object>.

The Maven dependency used in pom.xml:

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>${json.version}</version>
</dependency>

You can find the latest ${json.version} here.

Saikat
  • 14,222
  • 20
  • 104
  • 125
7

The best way to convert it to HashMap<String, Object> is this:

HashMap<String, Object> result = new ObjectMapper().readValue(jsonString, new TypeReference<Map<String, Object>>(){}));
Paritosh Gupta
  • 306
  • 3
  • 5
5

Note to the above solution (from A Paul): The solution doesn't work, cause it doesn't reconstructs back a HashMap< String, Object > - instead it creates a HashMap< String, LinkedHashMap >.

Reason why is because during demarshalling, each Object (JSON marshalled as a LinkedHashMap) is used as-is, it takes 1-on-1 the LinkedHashMap (instead of converting the LinkedHashMap back to its proper Object).

If you had a HashMap< String, MyOwnObject > then proper demarshalling was possible - see following example:

ObjectMapper mapper = new ObjectMapper();
TypeFactory typeFactory = mapper.getTypeFactory();
MapType mapType = typeFactory.constructMapType(HashMap.class, String.class, MyOwnObject.class);
HashMap<String, MyOwnObject> map = mapper.readValue(new StringReader(hashTable.toString()), mapType);
Stijn V
  • 358
  • 3
  • 13
1

Found out these problems can be addressed by using

ObjectMapper#convertValue(Object fromValue, Class<T> toValueType)

As a result, the origal quuestion can be solved in a 2-step converison:

  1. Demarshall the JSON back to an object - in which the Map<String, Object> is demarshalled as a HashMap<String, LinkedHashMap>, by using bjectMapper#readValue().

  2. Convert inner LinkedHashMaps back to proper objects

ObjectMapper mapper = new ObjectMapper(); Class clazz = (Class) Class.forName(classType); MyOwnObject value = mapper.convertValue(value, clazz);

To prevent the 'classType' has to be known in advance, I enforced during marshalling an extra Map was added, containing <key, classNameString> pairs. So at unmarshalling time, the classType can be extracted dynamically.

czerny
  • 15,090
  • 14
  • 68
  • 96
Stijn V
  • 358
  • 3
  • 13
1

I'll keep it further simple

There is an out of the box function available by name toMap() which should do the job

JSONObject jsonObject = new JSONObject(stringAsJson);
Map<String,Object> jsonMap = jsonObject.toMap();
Aditya Rewari
  • 2,343
  • 2
  • 23
  • 36
0

This is how I did it in Kotlin:

mutableMapOf<String, Any>().apply {
           jsonObj.keys().forEach { put(it, jsonObj[it]) }
       }
Cymatic
  • 1
  • 1
0
import com.alibaba.fastjson.JSONObject;


Map<String, Object> map = new HashMap<String, Object>();

JSONObject rec = JSONObject.parseObject(<JSONString>);

map.put(rec.get("code").toString(), rec.get("value").toString());
anson
  • 1,436
  • 14
  • 16
  • 2
    See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct, it doesn't explain why it solves the problem or should be the selected answer. We should educate along with helping solve the problem. – the Tin Man Mar 22 '22 at 05:15