Java Jersey/Jackson: return 动态 JSON 属性
Java Jersey/Jackson: return dynamic JSON properties
我们使用 jackson 将 java 对象 (DTO) 反序列化为 JSON 我们的端点。这很好用。但是,我有一个奇怪的问题。
假设我们有一个对象用户,并且我们有附加到该用户的元数据。元数据真的可以是客户能想到的任何东西,所以这是非常动态的。
客户端可以发出请求,以检索特定用户的特定元数据属性。假设客户想要拥有以下元数据属性:age 和 favouriteTree(因为有些人拥有一个,对吧?重点是,元数据可以是任何东西,而我们事先并不知道)。
我想return以下JSON:
{
"userId" : 1,
"age" : 22,
"favouriteTree" : "Maple Tree"
}
我可以简单地拥有一个 Java POJO,其中包含一个 int userId、int age 和一个 String favouriteTree。这样,我们可以让 Jackson 将其反序列化为 JSON,一切都很好。
但是,下次客户端使用相同的端点时,它可能会请求不同的属性,例如:colorEyes 和 favouriteFood,在这种情况下我想 return:
{
"userId" : 1,
"colorEyes" : "blue",
"favouriteFood" : "Pizza"
}
现在我需要另一个 Java POJO 来处理那些类型的元数据,并按照我们通常的方式对其进行反序列化。但是由于元数据可以是任何东西,我们不能那样做,因为我们不想继续向我们的代码中添加 POJO,因为不同的客户会有不同的需求。
在 Java 中是否有一种通用的方法可以做到这一点?
编辑:
我知道我可以做类似的事情:
{
"userId": 1,
"metadata": [{
"key": "colorEyes",
"value": "blue"
},
{
"key": "favouriteFood",
"value": "Pizza"
}
]
}
但我想尽可能避免这种情况。
您可以让端点 return 成为 JsonNode
,这样您就可以 return 任何类型的 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;
GraphQL 非常适合您的用例。
我知道你问的不是技术栈,但它正是你想要的。客户端将定义他们希望从服务中获得的数据,并且只会返回请求的数据。
而且您的服务将 maintain/extend 比您自己通过操纵 json 更简单、更容易。
检查此 link 以获得介绍:https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/
对于你说的情况,完全可以把你上面给的例子包起来,就像用map接受请求数据,然后把map转成json格式,就可以用
<dependency here. >
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
<scope>compile</scope>
</dependency>
这个jar里面的ObjectMapper工具class把地图转成json,像这样
public static String object2Json(Object o){
try{
return mapper.writeValueAsString(o);
}catch (Exception e){
log.warn("json serialize fail:", e);
return null;
}
}
我们使用 jackson 将 java 对象 (DTO) 反序列化为 JSON 我们的端点。这很好用。但是,我有一个奇怪的问题。
假设我们有一个对象用户,并且我们有附加到该用户的元数据。元数据真的可以是客户能想到的任何东西,所以这是非常动态的。
客户端可以发出请求,以检索特定用户的特定元数据属性。假设客户想要拥有以下元数据属性:age 和 favouriteTree(因为有些人拥有一个,对吧?重点是,元数据可以是任何东西,而我们事先并不知道)。
我想return以下JSON:
{
"userId" : 1,
"age" : 22,
"favouriteTree" : "Maple Tree"
}
我可以简单地拥有一个 Java POJO,其中包含一个 int userId、int age 和一个 String favouriteTree。这样,我们可以让 Jackson 将其反序列化为 JSON,一切都很好。
但是,下次客户端使用相同的端点时,它可能会请求不同的属性,例如:colorEyes 和 favouriteFood,在这种情况下我想 return:
{
"userId" : 1,
"colorEyes" : "blue",
"favouriteFood" : "Pizza"
}
现在我需要另一个 Java POJO 来处理那些类型的元数据,并按照我们通常的方式对其进行反序列化。但是由于元数据可以是任何东西,我们不能那样做,因为我们不想继续向我们的代码中添加 POJO,因为不同的客户会有不同的需求。
在 Java 中是否有一种通用的方法可以做到这一点?
编辑:
我知道我可以做类似的事情:
{
"userId": 1,
"metadata": [{
"key": "colorEyes",
"value": "blue"
},
{
"key": "favouriteFood",
"value": "Pizza"
}
]
}
但我想尽可能避免这种情况。
您可以让端点 return 成为 JsonNode
,这样您就可以 return 任何类型的 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;
GraphQL 非常适合您的用例。
我知道你问的不是技术栈,但它正是你想要的。客户端将定义他们希望从服务中获得的数据,并且只会返回请求的数据。
而且您的服务将 maintain/extend 比您自己通过操纵 json 更简单、更容易。
检查此 link 以获得介绍:https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/
对于你说的情况,完全可以把你上面给的例子包起来,就像用map接受请求数据,然后把map转成json格式,就可以用
<dependency here. >
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
<scope>compile</scope>
</dependency>
这个jar里面的ObjectMapper工具class把地图转成json,像这样
public static String object2Json(Object o){
try{
return mapper.writeValueAsString(o);
}catch (Exception e){
log.warn("json serialize fail:", e);
return null;
}
}