Java Джерси / Джексон: возвращать динамические свойства JSON - PullRequest
0 голосов
/ 24 октября 2019

Мы используем Джексон для десериализации объектов Java (DTO) в направлении JSON для наших конечных точек. Это хорошо работает. Однако у меня есть немного странный вопрос.

Допустим, у нас есть объект User, и к нему прикреплены метаданные. Метаданные могут быть тем, о чем может думать клиент, поэтому это очень динамично.

Клиент может сделать запрос, чтобы получить определенные свойства метаданных определенного пользователя. Допустим, клиент хочет иметь следующие свойства метаданных: age и favouriteTree (потому что у некоторых людей есть одно, верно? Дело в том, что метаданные могут быть чем угодно, и мы не знаем этого заранее).

IЯ хотел бы вернуть следующий JSON:

{
    "userId" : 1,
    "age" : 22,
    "favouriteTree" : "Maple Tree"
}

Я мог бы просто иметь Java POJO с int userId, int age и String favouriteTree. Таким образом, мы можем позволить Джексону десериализовать его в сторону JSON, и все хорошо.

Однако в следующий раз, когда клиент использует ту же конечную точку, он может запросить другие свойства, такие как: colorEyes и favouriteFood, в этом случае я бы хотел вернуть:

{
    "userId" : 1,
    "colorEyes" : "blue",
    "favouriteFood" : "Pizza"
}

Теперь мне понадобится еще один Java POJO для таких метаданных, чтобы десериализовать его, как мы это обычно делаем. Но поскольку метаданные могут быть любыми, мы не можем этого сделать, потому что мы не хотим продолжать добавлять POJO к нашему коду, поскольку разные клиенты будут иметь разные потребности.

Существует ли общий способсделать это на Java?

Редактировать:

Я знаю, что мог бы сделать что-то вроде:

{
    "userId": 1,
    "metadata": [{
            "key": "colorEyes",
            "value": "blue"
        },
        {
            "key": "favouriteFood",
            "value": "Pizza"
        }
    ]
}

Но я бы хотел этого избежать, если это возможно.

Ответы [ 3 ]

2 голосов
/ 24 октября 2019

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

Пример фрагмента кода:

JsonNode jn = // map some BaseDTO to JsonNode
ObjectNode on = (ObjectNode)jn; // We need to cast to ObjectNode for mutation
on.put("attribute", whateverValue);

return on;
1 голос
/ 24 октября 2019

GraphQL идеально подходит для вашего случая использования.

Я понимаю, что речь идет не о технологическом стеке, а о том, что вы хотите. Клиент определит данные, которые он хочет получить от сервиса, и будут возвращены только запрошенные данные.

И ваш сервис будет менее сложным и его будет проще поддерживать / расширять, чем делать это самостоятельно, манипулируя json.

Проверьте эту ссылку на вступление: https://www.graphql -java.com / tutorials / Getting-Start-with-Spring-Boot /

0 голосов
/ 24 октября 2019

В случае, который вы сказали, вы можете полностью обернуть приведенный выше пример, точно так же, как используя карту для принятия данных запроса, а затем преобразовав карту в формат json, вы можете использовать

<dependency here. >
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
       <version>2.9.9</version>
       <scope>compile</scope>
     </dependency>

Класс инструмента ObjectMapper в этом фляге, чтобы преобразовать карту в json , как это

public static String object2Json(Object o){
        try{
            return mapper.writeValueAsString(o);
        }catch (Exception e){
            log.warn("json serialize fail:", e);
            return null;
        }
    }
...