0

I'm building a SpringBoot Client (leveraging WebClient for the actual call) that will be retrieving data from a Vendor's REST API (so we have no control over the response structure). Regardless of the endpoint that is called, all responses are wrapped in either

{
    "data": {
        "attributes": {
            // DESIRED FIELDS
        }
    }
}

or

{
    "data": [
        {
            "attributes": {
                // DESIRED FIELDS
            }
        },
        {
            "attributes": {
                // SAME DESIRED FIELDS WITH DIFFERENT VALUES
            }
        },
        ...
    ]
}

The only way data + attributes would ever be used is to access the data wrapped within them, so I'm looking for an "invisible hand" that I could setup to automagically extract out and return only the inner POJO(s), preferably during the de-serialization process.

There are ~30 POJOs (which can be combined into any hierarchy/relationship structure as required) that have been created to represent the different responses we can get back from the vendor (packaged into an in-house jar for reuse), so writing a custom deserializer/builder/unpacker/etc for each one isn't really an option, and I'm hitting a wall trying to make a generic deserializer or decoder.

As we have no control/influence over the way the Vendor returns the data, leveraging Jackson's Polymorphic deserialization isn't an option here AFAIK, since there's no way to embed identity fields into the serialized data, nor are there any unique, native fields that could serve to reliably identify any given root/parent object in their JSON (the vendor loves to reuse generic fields, like id and name).

Given this, is there an approach that could allow for behind-the-scenes extraction? Even something like intercepting any JSON de-serialization attempt, looking for the data (both array + object permutations) + attribute fields, then manually manipulating the JSON into the desired structure would work, but I can't find any WebClient or Jackson documentation that suggests the existence of a, i guess "detour", de-serializer/decoder that would allow the chain to continue as normal after restructuring.

Worst comes to worst, I can create a generic wrapper class with helper methods to extract the underlying POJOs post-deserialization, and that can be used in combination with WebClient's chained calls, but that doesn't reduce the bloat/boilerplate all that much.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
Cameron Meyer
  • 65
  • 1
  • 9
  • 2
    I'm interested in hearing how you end up working with this. It looks like JSON:API (and I've tagged that), and I've written some not-ready-for-sharing support code for _writing_ all this, but not _reading_ it (which is a lot harder because JavaScript cowboys are happy to let `data` be an object or an array, link objects be a string or an object, etc.). I've contemplated attempting a general-purpose library but haven't started in yet. – chrylis -cautiouslyoptimistic- Nov 05 '20 at 01:08
  • I hadn't heard of JSON:API; thanks for the info on that! Unfortunately, from what I'm seeing it's basically just a standardized approach to Polymorphic Deserialization, and since our Vendor doesn't use type fields, I'm really struggling to see a route to a generic solution on this. I'm currently tossing around the idea of a two-step process, one that deserializes data + attributes, but stores the raw json in a sub field, then returns the raw json after passing it through a deserializer of a type the user passes in? Doesn't seem different than a wrapper class though – Cameron Meyer Nov 05 '20 at 16:25
  • 2
    Ah, I see. If the vendor is failing to include type fields (at the same level of `attributes`, not inside it!), then life is going to be obnoxious. Perhaps contact them and note this, asking for a fix? It's a violation of the JSON:API spec. (Note, of course, that even in best case JSON:API _is_ defining wrapper structure, and so I'm ending up with `JsonApiDataResponse>`.) – chrylis -cautiouslyoptimistic- Nov 05 '20 at 16:34
  • Unfortunately they haven't been particularly receptive, but its worth a try. And yup, but if there was a type field, it would be theoretically possible to write a de-serializer that could skip past the data + attributes fields to only deserialize the internal POJO, and let people register that when they make calls to the vendor right? This is probably getting too close to over-engineering, but since we know what POJO we'll want when we make the call to the vendor, would it be possible to manipulate the JSON before it gets deserialized to manually inject a type field? – Cameron Meyer Nov 05 '20 at 16:42
  • 1
    Actually, we wouldn't even have to use a custom deserializer. Seems like we could build in https://github.com/jasminb/jsonapi-converter to the POJO jar and that would take care of it for us, so long as we had a type field.... so close, yet so far – Cameron Meyer Nov 05 '20 at 16:51
  • Ooh, I wasn't even aware of that one. Thanks for the tip! – chrylis -cautiouslyoptimistic- Nov 05 '20 at 16:57

0 Answers0