简体   繁体   English

Java Jersey/Jackson:返回动态 JSON 属性

[英]Java Jersey/Jackson: return dynamic JSON properties

We use jackson to deserialize java objects (DTO's) towards JSON for our endpoints.我们使用 jackson 将 java 对象(DTO)反序列化到 JSON 的端点。 This works well.这很好用。 However, I have a bit on an odd question.但是,我有一个奇怪的问题。

Let's say we have an object User, and we have metadata attached to this user.假设我们有一个 object 用户,并且我们有附加到这个用户的元数据。 The metadata can really be anything the client can think of, so this is very dynamic.元数据实际上可以是客户能想到的任何东西,所以这是非常动态的。

The client can make a request, to retrieve certain metadata properties of a certain user.客户端可以发出请求,以检索某个用户的某些元数据属性。 Let's say the client wants to have the following metadata properties: age and favouriteTree (because some people have one, right? the point is, metadata can be anything, and we don't know this beforehand).假设客户希望拥有以下元数据属性:年龄和 favouriteTree(因为有些人有,对吗?关键是,元数据可以是任何东西,而我们事先并不知道这一点)。

I would like to return the following JSON:我想返回以下 JSON:

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

I could simply have a Java POJO with an int userId, int age, and a String favouriteTree in it.我可以简单地拥有一个 Java POJO,其中包含一个 int userId、int age 和一个 String favouriteTree。 This way, we can let Jackson deserialize it towards JSON and all is good.这样,我们可以让 Jackson 将其反序列化为 JSON,一切都很好。

However, the next time the client uses the same endpoint, it might request different properties, such as: colorEyes and favouriteFood, in which case I'd want to return:但是,下次客户端使用相同的端点时,它可能会请求不同的属性,例如:colorEyes 和 favouriteFood,在这种情况下我想返回:

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

Now I would need another Java POJO for just those kind of metadata as well to deserialize it the way we normally do.现在我需要另一个 Java POJO 来处理这些元数据,并像我们通常做的那样反序列化它。 But since the metadata can be anything, we can't do that, because we don't want to keep adding POJO's towards our code as different customers will have different needs.但是由于元数据可以是任何东西,我们不能这样做,因为我们不想继续在我们的代码中添加 POJO,因为不同的客户会有不同的需求。

Is there a generic kind of way to do this in Java?在 Java 中是否有一种通用的方法可以做到这一点?

Edit:编辑:

I know I could do something like:我知道我可以做类似的事情:

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

But I'd like to avoid that if possible.但如果可能的话,我想避免这种情况。

You could have the endpoint return a JsonNode , which would allow you to return any kind of json.您可以让端点返回一个JsonNode ,这将允许您返回任何类型的 json。 If you have some base DTO, you could map it to JsonNode , then include any dynamic parameters there.如果您有一些基本 DTO,您可以将其 map 到JsonNode ,然后在其中包含任何动态参数。

Code snippet example:代码片段示例:

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 is ideal for your use case. GraphQL 非常适合您的用例。

I understand that it is not the technology stack you are asking about, but it does exactly what you want.我知道这不是您要询问的技术堆栈,但它完全符合您的要求。 The client will define the data they want from the service and only the requested data will be returned.客户端将定义他们想要从服务中获得的数据,并且只返回请求的数据。

And your service will be less complicated and easier to maintain/extend than doing it yourself by manipulating json.与通过操作 json 自己进行服务相比,您的服务将更容易维护/扩展。

Check this link for an intro: https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/检查此链接以获取介绍: https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/

For the case you said, you can completely wrap the example you gave above, just like using map to accept the request data, and then converting the map to json format, you can use对于你说的情况,你可以完全包装你上面给出的例子,就像使用 map 接受请求数据,然后将 map 转换为 json 格式,你可以使用

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

The ObjectMapper tool class in this jar to convert the map to json,like this这个jar中的ObjectMapper工具class把map转换成json,像这样

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM