Mildfire
Mildfire

Reputation: 323

Json Mapping With Numbers as Property Names

I have the following json as an example:

{
    "success": true,
    "data": {
        "1": {
            "amount": "1"
        },
        "2": {
            "amount": "98"
        }
    }
}

Unfortunately, I have no control over the incoming JSON structure. I have been trying to find a way to map these to a DTO using JSONProperties, however I can't declare a property using a number.

Also I have tried iterating thought the JSON using JSONObject but I can't seem to get it to go through all child nodes, just the top level.

JSONObject payload = new JSONObject(jsonString);
JSONObject newPayload = payload;

Iterator<String> keys = payload.keys();

while (keys.hasNext()) {
                String key = keys.next();

                if (StringUtils.isNumber(key)) {
                    newPayload.put("element" + key, payload.get(key));
                    newPayload.remove(key);
                }
}

Has anyone come across a similar situation and found a solution.

All this to eventually have the JSON transformered into XML... Inherited this platform, no time for refactoring lol, not my choice.

Upvotes: 0

Views: 1331

Answers (3)

Dhruv Saraswat
Dhruv Saraswat

Reputation: 1132

If the incoming JSON structure is unknown, we can use recursion to parse the entire JSON (including the child nodes).

The below code will traverse the entire JSON and store it in a Map<String, Object>. We can whatever we want (like mapping the values to a DTO) either during the recursion itself, or we can again recursively traverse the Map<String, Object>.

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

private static Map<String, Object> parseMap(JSONObject jsonObject) {
    Map<String, Object> map = new HashMap<>();
    Set<String> keySet = jsonObject.keySet();
    for (String key : keySet) {
        Object value = jsonObject.get(key);

        if (value instanceof JSONArray) {
            value = parseList((JSONArray) value);
        } else if (value instanceof JSONObject) {
            value = parseMap((JSONObject) value);
        }
        // We can do whatever we want with a value of a key here.
        map.put(key, value);
    }
    return map;
}

private static List<Object> parseList(JSONArray array) {
    List<Object> list = new ArrayList<>();
    for (Object value : array) {
        if (value instanceof JSONArray) {
            value = parseList((JSONArray) value);
        } else if (value instanceof JSONObject) {
            value = parseMap((JSONObject) value);
        }
        // We can do whatever we want with an element of a JSON list here.
        list.add(value);
    }
    return list;
}

Driver code :-

JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(jsonString);

Map<String, Object> map = parseMap(jsonObject);
System.out.println("Resulting Map = " + map);

Upvotes: 0

There are a number of solutions, but assuming that you need only to deserialize this pathological structure, here's how I'd handle it (Groovy-style for compactness):

class ResponseData {
  Map<String, Long> amounts = new HashMap<>()  // or different key type


  static class WrappedAmount {
    String amount

    Long getAmountAsLong() {
      return Long.valueOf(amount)
    }
  }


  @JsonAnySetter  // this is the magic step
  void appendAmount(String key, WrappedAmount amount) {
    amounts.put(key, amount.getAmountAsLong())
  }
}


class Response {
  boolean success  // REST endpoints should use status codes, not properties
  ResponseData data
}

This will deserialize the response you have into a data structure that's manageable. If, as you suggested, these keys are indices and will be removed and replaced with something like an ordering of XML tags, you might want to replace HashMap with TreeMap so that you can just iterate over it to produce your output.

Upvotes: 1

talex
talex

Reputation: 20455

You can use @JsonProperty annotation and specify name.

@JsonProperty("1")
private String one;

Upvotes: 1

Related Questions