Доступ к глубоким объектам на карте с помощью ключа типа «item1.item1A»

#java #maps #key

#java #Карты #Клавиша

Вопрос:

У меня есть несколько карт, ключами которых являются строки, а объектами их значений ( Map<String, Object> ). Этими объектами могут быть другие карты, списки или литеральные значения (аналогично представлению JSON в памяти). Пример:

 myMap = {
  "users": [
    {
      "name": "Foo",
      "surname": "Bar"
    },
    {
      "name": "John",
      "surname": "Doe"
    }
  ]
}
  

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

 String secondUserSurname = (String) myMap.get("users[1].surname");
  

Спасибо

РЕДАКТИРОВАТЬ: Чтобы уточнить, мне нужно, чтобы выражение «пользователи [1].фамилия» было строкой. У меня была бы эта структура данных в памяти, а выражение — в файле .properties. Файл свойств укажет, к какому объекту на карте обращаться. Таким образом, я могу быстро изменить объект для доступа, изменив файл свойств, без изменения кода Java, который потребовал бы дорогостоящего развертывания.

Комментарии:

1. Вы не можете получить доступ к Map элементу по индексу, Map так не работает. Почему бы вам вместо этого не использовать List реализацию?

2. Почему бы вам просто не использовать JSON в первую очередь, если он ведет себя подобным образом?

3. @TA myMap — это карта, которая содержит запись, ключом которой является «пользователи». Значением этой записи является список<Object>, содержащий две карты. Каждая карта содержит две записи с ключами «имя» и «фамилия». Таким образом, доступ к myMap.get («пользователи») должен возвращать список<Object>, а myMap.get(«пользователи[1]») должен возвращать объект.

4. @Lino Я мог бы использовать JSON, но могу ли я оценить его на Java? Мне нужно, чтобы выражение «пользователи [1].фамилия» было строкой, потому что эта строка будет находиться в файле свойств и может быть отредактирована в любое время для доступа к различным объектам на карте.

5. FWIW, возможно, вы захотите проверить Commons:JXPath

Ответ №1:

Если у вас есть контент, доступный как String или bytes , вы можете использовать любую json библиотеку для десериализации его в POJO и получения полей. Ниже приведен пример с Джексоном:

 class UserObject {
    private List<User> users;

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }
}

class User {
    private String name;
    private String surname;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSurname() {
        return surname;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
}
  

Код драйвера:

 String content = "{"   
        "  "users": ["   
        "    {"   
        "      "name": "Foo","   
        "      "surname": "Bar""   
        "    },"   
        "    {"   
        "      "name": "John","   
        "      "surname": "Doe""   
        "    }"   
        "  ]"   
        "}";

ObjectMapper objectMapper = new ObjectMapper();
UserObject userObject = objectMapper.readValue(content, UserObject.class);
System.out.println(userObject.getUsers().get(0).getSurname());
  

Ответ №2:

Библиотека, которая позволяет мне получать доступ к этим объектам, — это JXPath, как указал Gyro Gearless в комментариях, заслуга его.

https://commons.apache.org/proper/commons-jxpath/