2

I have a problem during the deserialization of a response. Let's suppose I have this response from third party using webclient .

Response : 
{
   "name":"FirstName",
   "type":"Steel",
   "Fee":{
      "id":"1234",
      "name":"FeeFirstName"
   },
   "address":"2nd Street"
}

This is how my pojo classes looks like

public class Fee{} //generic OR empty class

public class Foo{
  private String name;
  private String type;
  private Fee fee;
  private String address;
}

My webclient get response code :

@Autowired
private WebClient fooWebClient;

public Foo getFoo()
{
try{
     return fooWebClient.get()
        .uri(uriBuilder -> uriBuilder.path("/foo/fee").build("123"))
        .header(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE)
        .accept(MediaType.APPLICATION_JSON)
        .retrieve()
        .bodyToMono(Foo.class)
        .block();
    }catch(Exception e){throw new ApiClientException(e.getMessage());}

}

The above webclient getFoo() code is not giving me the full response, the Fee is coming blank stating "Class has no fields". Rest of the values are coming properly in response. Fee needs to be empty as any other object can also come.

Please let me know how to deserialize the whole response.

Olivier
  • 13,283
  • 1
  • 8
  • 24
  • Can you please add the full error you are getting? – Stempler Aug 16 '22 at 07:11
  • *"Fee needs to be empty as any other object can also come"* I don't understand what it means. – Olivier Aug 16 '22 at 07:53
  • @Stempler its actually not error as i said above. For rest of the attributes the values are coming properly. The values/object is not coming for Fee. In response its says "Class has no fields". – Kumar Kartikeya Aug 16 '22 at 08:55
  • @Olivier by that I meant that the class wont be having any attribute or methods. – Kumar Kartikeya Aug 16 '22 at 08:57
  • 1
    what do you mean by values are coming in properly? How is the full response looks like? What http code are you getting? When you deserialize the response into an object, it will always be empty as you provided no fields in it. – Stempler Aug 16 '22 at 11:24
  • if the class (`Fee`) has no fields, nothing can be added there when deserialized (because there is nothing to deserialize to). Maybe you have seen such behavior somewhere or you are mistaken. This cannot work. Use `Map` as answered below if you want a generic structure – vladtkachuk Aug 17 '22 at 14:01

3 Answers3

5

You don't need the Fee class, you can get rid of it entirely and use a Map instead:

public class Foo {
  private String name;
  private String type;
  private Map<String, Object> fee;
  private String address;
}
lkatiforis
  • 5,703
  • 2
  • 16
  • 35
3

We cannot dynamically create POJO and hence we are left with two options.

  1. Add necessary fields to the 'Fee' class (If you know Fee structure upfront)
  2. If you are not sure about the 'Fee' structure go for Map.
0

Because spring integrates Jackson you can create a custom Jackson JSON Deserializer for the Fee class that gives you more control:

@JsonDeserialize(using = FeeDeserializer.class)
public class Fee {

    private String id;
    private String name;

    public Fee(String id, String name) {
        this.id = id;
        this.name = name;
    }
}

import com.fasterxml.jackson.*;
    
public class FeeDeserializer extends JsonDeserializer<Fee> {

    @Override
    public Fee deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
        ObjectCodec codec = jsonParser.getCodec();
        JsonNode tree = codec.readTree(jsonParser);

        JsonNode id = tree.get("id");
        JsonNode name = tree.get("name");

        return (id != null && name != null) ? new Fee(id.asText(), name.asText()) : null;
    }

}

For more details see

tscz
  • 113
  • 7