Rens Groenveld
Rens Groenveld

Reputation: 982

Java Jersey/Jackson: return dynamic JSON properties

We use jackson to deserialize java objects (DTO's) towards JSON for our endpoints. 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. 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).

I would like to return the following 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. This way, we can let Jackson deserialize it towards JSON and all is good.

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:

{
    "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. 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.

Is there a generic kind of way to do this in 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.

Upvotes: 0

Views: 677

Answers (3)

Kayaman
Kayaman

Reputation: 73568

You could have the endpoint return a JsonNode, which would allow you to return any kind of json. If you have some base DTO, you could map it to JsonNode, then include any dynamic parameters there.

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;

Upvotes: 2

zark
zark

Reputation: 11

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

<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

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

Upvotes: -1

martidis
martidis

Reputation: 2975

GraphQL is ideal for your use case.

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.

Check this link for an intro: https://www.graphql-java.com/tutorials/getting-started-with-spring-boot/

Upvotes: 1

Related Questions