1

I have a JSON that I'm getting from some external system. I need to convert that JSON into key value based on my system mapping. For instance:

JSON from external system:

   [{
        "name": "Tim",
        "address": "New York",
        "education" : {
             "university": "XYZ"     
          }
    },
    {
        "name": "Steve",
        "address": "UK"
    }]

I have following mapping that we need to use:

{
"name": "firstName",
"address": "location",
"university": "college"
}

i.e name to be mapped to firstName and address to be mapped to location. And finally, my processed mapped will look like:

       [{
            "firstName": "Tim",
            "location": "New York"
            "education" : {
             "college": "XYZ"     
             }
        },
        {
            "firstName": "Steve",
            "location": "UK"
        }]

What can be the best way to achieve this? Should I use normal hashmap operations or is there any other efficient way. I was checking JSONNode for this purpose, but the approach was similar to hash map. Is there any utility I can use to traverse tree like json map and replace the key?

codeluv
  • 305
  • 1
  • 15

1 Answers1

0

I'm a fan of Jackson which you can use to traverse the JSON. As you do so, populate a list of maps, using your system mapping to replace whatever keys are encountered that have a mapping, leaving the others as is. At the end, dump the list of maps back out as JSON.

Edit: adding code example below

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;

import java.io.IOException;
import java.util.*;

public class ReplaceKeys {
    private static final ObjectMapper mapper = new ObjectMapper();

    private static Map<String, String> keymap;
    static {
        try {
            // Create the key map based on the json provided by OP
            keymap = mapper.readValue("{\n" +
                    "\"name\": \"firstName\",\n" +
                    "\"address\": \"location\",\n" +
                    "\"university\": \"college\"\n" +
                    "}", Map.class);
        } catch (IOException e) {
            System.out.println("whoops");
        }
    }

    public static String mapKeys(String input) throws IOException {
        // Assume the input is an array and therefore so is the output.
        List<Map<String, Object>> output = new ArrayList<>();
        ArrayNode inputArray = (ArrayNode) mapper.readTree(input);
        for (JsonNode node : inputArray) {
            output.add(mapKeys(node));
        }
        return mapper.writeValueAsString(output);
    }

    private static Map<String, Object> mapKeys(JsonNode node) {
        Map<String, Object> map = new HashMap<>();
        for (Iterator<String> iterator = node.fieldNames(); iterator.hasNext(); ) {
            String key = iterator.next();
            key = keymap.containsKey(key) ? keymap.get(key) : key;
            for (JsonNode child : node) {
                if (node.isValueNode()) {
                    // This is coercing everything to a String. You could dig into using
                    // proper types based on node.getNodeType().
                    map.put(key, node.asText());
                } else {
                    map.put(key, mapKeys(child));
                }
            }
        }
        return map;
    }
}

fram
  • 1,551
  • 1
  • 7
  • 7