Как бороться с вложенным статическим приведением? - PullRequest
0 голосов
/ 26 ноября 2018

У меня просто есть Map.Но он может вернуть Map, который также может вернуть Map.Возможно до 3 до 4 вложенных Map с.Поэтому, когда я хочу получить доступ к вложенному значению, мне нужно сделать следующее:

((Map)((Map)((Map)CacheMap.get("id")).get("id")).get("id")).get("id")

Есть ли более чистый способ сделать это?

Причина, по которой я использую Mapвместо того, чтобы сопоставить его с объектом для удобства сопровождения (например, когда появляются новые поля).

Примечание:

Map<String, Object>

Имеетбыть Object, потому что он не всегда возвращает Hashmap.Он может вернуть String или Long.

Дополнительные пояснения:

Что я делаю, так это то, что я вызываю API, который возвращает json ответ, который я сохраняю как Map.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

Если вы не знаете глубины дерева JSON и беспокоитесь о возможности сопровождения, если добавляются новые поля, я бы рекомендовал не десериализовать полное дерево на карте, а использовать низкоуровневый синтаксический анализатор.

Например, если ваш JSON выглядит следующим образом:

{
    "id": {
        "id": {
            "id": {
                "id": 22.0
             }
         }
     }
}

Вы можете написать что-то подобное, чтобы получить идентификатор, используя Джексона:

public Object getId(String json) throws JsonParseException, IOException
{
    ObjectMapper mapper = new ObjectMapper();
    JsonNode root = mapper.readTree(json);

    JsonNode id = root.get("id");
    while (id != null && id.isObject())
    {
        id = id.get("id");
    }

    //Cannot find a JsonNode for the id
    if (id == null)
    {
        return null;
    }

    //Convert id to either String or Long
    if (id.isTextual())
        return id.asText();

    if (id.isNumber())
        return id.asLong();

    return null;
}
0 голосов
/ 26 ноября 2018

Вот некоторые вспомогательные методы, которые могут помочь вещам казаться чище и более читабельными:

@SuppressWarnings("unchecked")
public static Map<String, Object> getMap(Map<String, Object> map, String key) {
    return (Map<String, Object>)map.get(key);
}

@SuppressWarnings("unchecked")
public static String getString(Map<String, Object> map, String key) {
    return (String)map.get(key);
}

@SuppressWarnings("unchecked")
public static Integer geInteger(Map<String, Object> map, String key) {
    return (Integer)map.get(key);
}

// you can add more methods for Date, Long, and any other types you know you'll get

Но вам придется вложить вызовы:

String attrValue = getString(getMap(getMap(map, id1), id2), attrName);

Или, если вы хотите что-то более прикольное, добавьте вышеуказанные методы в качестве методов экземпляра к карте impl:

public class FunkyMap extends HashMap<String, Object> {
    @SuppressWarnings("unchecked")
    public FunkyMap getNode(String key) {
        return (FunkyMap)get(key);
    }

    @SuppressWarnings("unchecked")
    public String getString(String key) {
        return (String)get(key);
    }

    @SuppressWarnings("unchecked")
    public Integer geInteger(String key) {
        return (Integer)get(key);
    }

    // you can add more methods for Date, Long, and any other types you know you'll get
}

Десериализовать в этот класс с вашей библиотекой json (вам, вероятно, придется предоставить ее).с фабричным методом для класса карты (), тогда вы можете цепочка вызовы более естественно:

String attrValue = map.getNode(id1).getNode(id2).getString(attrName);

Прикольный вариант - это то, что я сделал для компании, и он работаллечить :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...