Deserializing different json representations into a one java object

1,447 views
Skip to first unread message

chetan choulwar

unread,
Sep 7, 2017, 2:03:58 PM9/7/17
to jackson-dev
Hi All,

I'm calling different REST APIs and getting different kinda JSON responses; is there any way to pick particular attribute from different JSON responses and map it to a one common property of defined POJO (Resource for my API) that can then be sent as a response from the REST API that I've exposed?

For Example:
By calling REST API "https://xyz.com/resources/resource" gives me {"name":"abc.txt"}
and calling "https://abc.com/resources/resource" gives me {"title":"idontknow.txt"}

And I have one resource class defined for my APIs to return i.e.
MyResource
{
   String fileName;
}

So is there any way that I can map "name"/"title" to fileName i.e. how can I use jackson to deserialize these jsons to MyResource type?

Please let me know if this is valid? and if yes, how? 

Tatu Saloranta

unread,
Sep 7, 2017, 11:49:49 PM9/7/17
to jacks...@googlegroups.com
If you have many different names to use, it may be simpler to just
bind JSON to `Map` or `JsonNode`, and extract value explicitly.

But if there are just couple of values, you can use `@JsonAlias` like:

public class POJO {
@JsonAlias({ "name", "title" })
public String fileName;
}

which would then accept alternate names "name" and "title", but
serialize as "fileName" (which it also accepts).
This annotations was added in Jackson 2.9

-+ Tatu +-

chetan choulwar

unread,
Sep 8, 2017, 8:13:36 AM9/8/17
to jackson-dev
Thanks a lot for your input. I tried it and it worked as expected. But I'm stuck at a situation where I want to retrieve a value from nested block, so can you help me out?
For example,

By calling REST API "https://xyz.com/resources/resource" gives me {
                                                                                                      "value"={"name":"abc.txt"}
                                                                                                    }
and calling "https://abc.com/resources/resource" gives me {"title":"idontknow.txt"}
now how can I take name out from the first json response?

Once again thanks a lot for your answer..!:)

Tatu Saloranta

unread,
Sep 9, 2017, 11:51:55 PM9/9/17
to jacks...@googlegroups.com
On Fri, Sep 8, 2017 at 5:13 AM, chetan choulwar <cheta...@gmail.com> wrote:
> Thanks a lot for your input. I tried it and it worked as expected. But I'm
> stuck at a situation where I want to retrieve a value from nested block, so
> can you help me out?
> For example,
> By calling REST API "https://xyz.com/resources/resource" gives me {
>
> "value"={"name":"abc.txt"}
>
> }
> and calling "https://abc.com/resources/resource" gives me
> {"title":"idontknow.txt"}
> now how can I take name out from the first json response?
>
> Once again thanks a lot for your answer..!:)

I am not sure why my first answer wouldn't work here. All you are
doing is specifying that property name in json is an alias that can be
used for property in POJO, so you would access it with field name (or
getter) you have.

But at the same time if these are effectively different objects it is
unclear why same Java class should be used anyway -- perhaps they
should use different POJOs.

-+ Tatu +-
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-dev...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

chetan choulwar

unread,
Sep 10, 2017, 12:58:28 AM9/10/17
to jackson-dev
That @JsonAlias worked fine. But my problem is with nested elements, how can I specify nested json element into alias?
And reason for doing so is that I'm writing an API that will send the common response out of all these different APIs I am calling from my API.
Apart from this it'd be great if you can you mail me a link where I can find latest documentation and hands-on for the same.

Thanking you in anticipation..!

Tatu Saloranta

unread,
Sep 10, 2017, 12:30:21 PM9/10/17
to jacks...@googlegroups.com
On Sat, Sep 9, 2017 at 9:58 PM, chetan choulwar <cheta...@gmail.com> wrote:
> That @JsonAlias worked fine. But my problem is with nested elements, how can
> I specify nested json element into alias?

You can't. If your structures differ beond just naming you need to do
something else.
Databinding is meant to match incoming document structure to a Java
object graph and vice versa.
It is not designed to allow arbitrary transformation, or unification
of differing structures into single model.

It is possible to unify differing structures, of course, but that is
true transformation and something explicitly
out of scope for Jackson. You can use `JsonNode` as structure modify,
for input and output structures, and it is possible
to change structure any way you want. But you have to write that
transformation yourself.
Or you can use separate Java classes for input(s) and output.

> And reason for doing so is that I'm writing an API that will send the common
> response out of all these different APIs I am calling from my API.

I am still not sure I fully understand your usage, still; this is very
generic explanation.

But assuming I do understand... if input data you get from a service
differs, you should consider separating handling of your input from
constructing your output. Do not try to use same set of objects if
structures are not same or similar enough. Trying to do that is false
savings and tends to sacrifice clean design for seeming savings.

This assuming I actually understood what you are trying to do --
without full explanation of steps from calling another service to
formulating output it is possible to misunderstand intent.

> Apart from this it'd be great if you can you mail me a link where I can find
> latest documentation and hands-on for the same.
>
> Thanking you in anticipation..!

Documentation hub is at:

https://github.com/FasterXML/jackson-docs

and main portal

https://github.com/FasterXML/jackson/

has some links.

-+ Tatu +-

chetan choulwar

unread,
Sep 10, 2017, 3:19:29 PM9/10/17
to jackson-dev
Okay..Let me help you with one real time example. Consider for an example different tv channels have exposed their APIs to get list of programs telecast-ed on them. And now suppose I'm trying to expose one APIs that will accept channel name and provide the list of programs for that particular channel by calling it from my API and converting the response received in my own format (a common one). The kind of data I'm getting from different APIs is same but their representation is somewhat different, and what I want to do is to convert these responses into a common format defined by my API and send it as a response from my API. 
So now that I'm sure that I'm dealing with same kinda data represented somewhat different, is it okay to convert it into common format?
Currently I'm doing this by mapping each of the responses to JsonNode only, but every time I add a new common API I need to write different logic to convert the new response into a common one and that to for different APIs I'm calling from my API.
If any kinda JSON response can be mapped to JsonNode, isn't is possible to map these different responses to any particular format? I mean can I write my resource object in such a way that I'd be able to map these different json responses representing same kinda data to my own resource, in some way, instead of doing manually by traversing through json tree?

Hope it is clear to now..Initially I thought it's impossible, but you gave me direction and I do believe now there'd be some way that I can bind these different resources to common one. May be the way json objects are mapped to JsonNode.

Please let me know if this is clear to you, as right now you the only hope I can see.!

Thank you Tatu..!

chetan choulwar

unread,
Sep 10, 2017, 3:25:28 PM9/10/17
to jackson-dev
You can consider my API as a proxy for connecting to different APIs providing similar kinda data represented in somewhat different way than each other. 

chetan choulwar

unread,
Sep 11, 2017, 5:05:12 AM9/11/17
to jackson-dev
Hello Tatu,

I found this post on stackoverflow which matches the exact scenario I was trying to explain you. It says: The actual JSON response I'm trying to parse is very complex, and I don't want to have to create an entire new class for every sub-node, even though I only need a single field.
This page led me to a library called Elastic Path's JSON Unmarshaller . It will solve my problem, but just wanted to make sure with you if this library is stable and recommended?
Please comment on this.

Thanks a lot..! 

Tatu Saloranta

unread,
Sep 11, 2017, 6:33:34 PM9/11/17
to jacks...@googlegroups.com
On Sun, Sep 10, 2017 at 12:19 PM, chetan choulwar <cheta...@gmail.com> wrote:
> Okay..Let me help you with one real time example. Consider for an example
> different tv channels have exposed their APIs to get list of programs
> telecast-ed on them. And now suppose I'm trying to expose one APIs that will
> accept channel name and provide the list of programs for that particular
> channel by calling it from my API and converting the response received in my
> own format (a common one). The kind of data I'm getting from different APIs
> is same but their representation is somewhat different, and what I want to
> do is to convert these responses into a common format defined by my API and
> send it as a response from my API.
> So now that I'm sure that I'm dealing with same kinda data represented
> somewhat different, is it okay to convert it into common format?

Yes, but I don't think you should try to use just one single Java
class for all of that.

It makes sense to use one class for representing output to your users,
but I think that if input structures, names vary,
then POJOs to map them to should be different too. You may reuse some
of those for "similar enough" inputs,
but there are limits to how far this helps.
I mean, you will always have to do some work anyway when adopting new
inputs -- even if just adding annotations.
So question there becomes: what approaches is easiest, most reliable
to maintain?

> Currently I'm doing this by mapping each of the responses to JsonNode only,
> but every time I add a new common API I need to write different logic to
> convert the new response into a common one and that to for different APIs
> I'm calling from my API.
> If any kinda JSON response can be mapped to JsonNode, isn't is possible to
> map these different responses to any particular format? I mean can I write
> my resource object in such a way that I'd be able to map these different
> json responses representing same kinda data to my own resource, in some way,
> instead of doing manually by traversing through json tree?
>
> Hope it is clear to now..Initially I thought it's impossible, but you gave
> me direction and I do believe now there'd be some way that I can bind these
> different resources to common one. May be the way json objects are mapped to
> JsonNode.
>
> Please let me know if this is clear to you, as right now you the only hope I
> can see.!
>
> Thank you Tatu..!

It may make sense to map input you get into `JsonNode` and have
separate code to traverse them;
or to have a set of Input POJOs and code to convert from those to
result/output POJO.
There are pros and cons to each approach.

Tatu Saloranta

unread,
Sep 11, 2017, 6:35:27 PM9/11/17
to jacks...@googlegroups.com
On Mon, Sep 11, 2017 at 2:05 AM, chetan choulwar <cheta...@gmail.com> wrote:
> Hello Tatu,
>
> I found this post on stackoverflow which matches the exact scenario I was
> trying to explain you. It says: The actual JSON response I'm trying to parse
> is very complex, and I don't want to have to create an entire new class for
> every sub-node, even though I only need a single field.
> This page led me to a library called Elastic Path's JSON Unmarshaller . It
> will solve my problem, but just wanted to make sure with you if this library
> is stable and recommended?
> Please comment on this.
>
> Thanks a lot..!

That sounds like a potentially useful library. I have had good
experiences with Elastic Search in general,
although I am not familiar with this specific component. It does
support kind of transformations so if it seems
to match your use case you may want to use it.
I can't comment on stability, but as I said Elastic project has been
pretty good from all I know so I would
expect it to work as advertised.

I hope this helps,

-+ Tatu +-

chetan choulwar

unread,
Sep 12, 2017, 6:28:58 AM9/12/17
to jackson-dev
This actually sounds good to have one POJO defined for each of the input JSON that is being dealt and that's what the way I was thinking but was not able to map nested json elements to shallow (class level) pojo properties(To avoid multiple POJOs for nested json objects). Well now that I've this elastic library at hand I can have one POJO defined for each input json and can use polymorphic deserialization then.

Thanks a lot for your inputs Tatu..!:)

chetan choulwar

unread,
Sep 22, 2017, 7:31:12 AM9/22/17
to jackson-dev
Do we have anything like @XMlPath in jackson?

Tatu Saloranta

unread,
Sep 22, 2017, 9:17:55 PM9/22/17
to jacks...@googlegroups.com
On Fri, Sep 22, 2017 at 4:31 AM, chetan choulwar <cheta...@gmail.com> wrote:
> Do we have anything like @XMlPath in jackson?

I don't know what exactly @XMLPath does, but if it is something for
referencing to sub-trees, no.
@JsonUnwrapped is the only annotation that does something similar.

-+ Tatu +-

chetan choulwar

unread,
Sep 25, 2017, 9:37:00 AM9/25/17
to jackson-dev
Could you please have a look at following link: here? So that it'll be easy for you to understand exactly where I am stuck and bcoz of which I can neither go with Jackson nor with MOXy as each one is lacking something that doesn't satisfy my requirement.

  And please suggest me to how to proceed with this kinda scenario with Jackson.

Thanking you in anticipation..!
Reply all
Reply to author
Forward
0 new messages