13

I'm trying to simplify my code: I want to store key and values (all strings).

I'm actually using a Map<String, Object> to store it. hat way Object could be a value (String) or a new node (Map<String, Object>).

How could I simplify this code? A recursive function would be good.

try {
    JsonParser jsonParser = new JsonFactory().createJsonParser(content);

    jsonParser.nextToken();
    while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
        jsonParser.nextToken();

        if (jsonParser.getCurrentToken() == JsonToken.START_OBJECT) {
            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                String key = jsonParser.getCurrentName();
                jsonParser.nextToken();

                if (jsonParser.getCurrentToken() == JsonToken.START_OBJECT) {
                    mData.put(key, new HashMap<String, Object>());
                    while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                        String subkey = jsonParser.getCurrentName();
                        jsonParser.nextToken();

                        if (jsonParser.getCurrentToken() == JsonToken.START_OBJECT) {
                            Map<String, Object> subdata = (Map<String, Object>) mData.get(key);
                            subdata.put(subkey, new HashMap<String, Object>());
                            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
                                String subsubkey = jsonParser.getCurrentName();
                                jsonParser.nextToken();
                                Map<String, Object> subsubdata = (Map<String, Object>) subdata.get(subkey);
                                LogHelper.d("data[" + key + "][" + subkey + "][" + subsubkey + "]=" + jsonParser.getText());
                                subsubdata.put(subsubkey, jsonParser.getText());
                            }
                        }
                        else {
                            LogHelper.d("data[" + key + "]=" + jsonParser.getText());
                            mData.put(key, jsonParser.getText());
                        }
                    }
                }
                else {
                    LogHelper.d("data[" + key + "]=" + jsonParser.getText());
                    mData.put(key, jsonParser.getText());
                }
            }
        }
        else {
            LogHelper.d("status=" + jsonParser.getText());
            mStatus = jsonParser.getText();
        }
    }
}
catch (IllegalArgumentException e) {
    error("0", "IllegalArgumentException: " + e.getMessage());
}
catch (JsonParseException e) {
    error("0", "IOException: " + e.getMessage());
}
catch (IOException e) {
    error("0", "IOException: " + e.getMessage());
}
darcyy
  • 5,236
  • 5
  • 28
  • 41
shkschneider
  • 17,833
  • 13
  • 59
  • 112

1 Answers1

34

Assuming that your end goal is just to deserialize JSON into a Map<String, Object>, there is a far simpler way to do this with Jackson. Using ObjectMapper:

final String json = "{}";
final ObjectMapper mapper = new ObjectMapper();
final MapType type = mapper.getTypeFactory().constructMapType(
    Map.class, String.class, Object.class);
final Map<String, Object> data = mapper.readValue(json, type);

You will need error handling etc, but this is a good starting point.

Perception
  • 79,279
  • 19
  • 185
  • 195
  • Indeed, using `jackson-core` and `jackson-mapper` libraries made your code works with only 3 lines! Thanks! – shkschneider Dec 18 '12 at 17:18
  • In case somebody finds this answer and is curious about this: to make it work the other way round, you can use `String json = new ObjectMapper().writeValueAsString(data)`. I had a `Map` from an API gateway in my case and needed something like a `String json` or [an `ApiGatewayResponse`](https://github.com/serverless/examples/blob/master/aws-java-simple-http-endpoint/src/main/java/com/serverless/ApiGatewayResponse.java) (which contains such a String). – Cadoiz Sep 15 '21 at 14:38