Как заменить ключи в карте на основе сопоставления - PullRequest
1 голос
/ 07 мая 2020

У меня есть JSON, которое я получаю от какой-то внешней системы. Мне нужно преобразовать это JSON в значение ключа на основе сопоставления моей системы. Например:

JSON из внешней системы:

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

У меня есть следующее сопоставление, которое нам нужно использовать:

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

т.е. имя, которое будет сопоставлено firstName и адрес для сопоставления с местоположением. И, наконец, обработанное мной сопоставление будет выглядеть так:

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

Как лучше всего этого добиться? Должен ли я использовать обычные операции с хэш-картами или есть другой эффективный способ. Я проверял JSONNode для этой цели, но подход был похож на ha sh map. Есть ли какая-нибудь утилита, которую я могу использовать для обхода дерева, такого как карта json, и замены ключа?

1 Ответ

0 голосов
/ 08 мая 2020

Я фанат Джексона, который вы можете использовать, чтобы пройти JSON. При этом заполните список карт, используя системное сопоставление, чтобы заменить все встречающиеся ключи, у которых есть сопоставление, оставив остальные как есть. В конце выгрузите список карт как JSON.

Изменить: добавив пример кода ниже

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;
    }
}

...