Search code examples
javaspring-bootjacksonspring-webfluxspring-webclient

How to deal with different JSON Response in Spring


I'm using Spring WebClient to make REST requests. I've created POJO's to store the JSON properties but there's a problem. If a word on the API I'm using doesnt exist, It returns an array of words

[
  "testified",
  "the last\/final word",
  "testify for",
  "Lakewood",
  "foreword",
  "headword",
  "lakewood",
  "sent word",
  "swearword",
  "testament",
  "testamentary",
  "testaments",
  "tested",
  "tester",
  "testers",
  "testier",
  "testosterone",
  "the f-word",
  "the final word",
  "true to her word"
]

But my Controller expects a specific Java Class. How do I deal with that? I'm a beginner with WebClient, so I also accept supplementary material. Also, How do I handle error messages returned as JSON?

Service

public List<Dicionario> getWords(String palavra) {                     
        Flux<Dicionario> fluxDicionario = this.webClient
            .get()
            .uri(builder -> builder.path("/"+palavra).queryParam("key", APIKey).build())
            .retrieve() //Retorna o response-spec
            .bodyToFlux(Dicionario.class);                

        List<Dicionario> dicionarios = new ArrayList<>();
        dicionarios = fluxDicionario.collectList().block();            
   
        return dicionarios;
    }

@Edit

Normal Response:

[
  {
    "meta": {
      "id": "ball:1",
      "uuid": "8e3b4ecd-33ab-4345-bec7-14560aac1853",
      "src": "learners",
      "section": "alpha",
      "highlight": "yes",
      "stems": [
        "ball",
        "balls",
        "on the ball",
        "carry the ball",
        "drop the ball",
        "get/set/start the ball rolling",
        "get the ball rolling",
        "set the ball rolling",
        "start the ball rolling",
        "keep the ball rolling",
        "keep your eye on the ball",
        "play ball",
        "the ball is in your court"
      ],
      "app-shortdef": {
        "hw": "ball:1",
        "fl": "noun",
        "def": [
          "{bc} a usually round object that is used in a game or sport or as a toy",
          "{bc} something that has a round shape",
          "{bc} a round bullet shot out of an old-fashioned gun"
        ]
      },
      "offensive": true
    },
    "hom": 1,
    "hwi": {
      "hw": "ball",
      "prs": [
        {
          "ipa": "ˈbɑːl",
          "sound": {
            "audio": "ball0001"
          }
        }
      ]
    },
    "fl": "noun",
    "ins": [
      {
        "il": "plural",
        "if": "balls"
      }
    ],
    "def": [
      {
        "sseq": [
          [
            [
              "sense",
              {
                "sn": "1",
                "sgram": "count",
                "dt": [
                  [
                    "text",
                    "{bc}a usually round object that is used in a game or sport or as a toy "
                  ],
                  [
                    "vis",
                    [
                      {
                        "t": "a tennis/soccer {it}ball{/it}"
                      },
                      {
                        "t": "golf/billiard/bowling {it}balls{/it}"
                      },
                      {
                        "t": "a toy rubber {it}ball{/it}"
                      },
                      {
                        "t": "kick/throw/hit/catch/bounce/dribble the {it}ball{/it}"
                      }
                    ]
                  ]
                ]
              }
            ]
          ],
          [
            [
              "sense",
              {
                "sn": "2",
                "sgram": "count",
                "dt": [
                  [
                    "text",
                    "{bc}something that has a round shape "
                  ],
                  [
                    "vis",
                    [
                      {
                        "t": "a {it}ball{/it} of string"
                      },
                      {
                        "t": "She uses cotton {it}balls{/it} to clean her face."
                      },
                      {
                        "t": "eating rice/melon {it}balls{/it}"
                      }
                    ]
                  ]
                ]
              }
            ]
          ],
          [
            [
              "sense",
              {
                "sn": "3",
                "sgram": "count",
                "dt": [
                  [
                    "text",
                    "{bc}a round bullet shot out of an old-fashioned gun"
                  ]
                ]
              }
            ]
          ],
          [
            [
              "sense",
              {
                "sn": "4",
                "sgram": "count",
                "dt": [
                  [
                    "text",
                    "{bc}the rounded part of the human foot that is at the bottom of the foot and behind the toes"
                  ],
                  [
                    "uns",
                    [
                      [
                        [
                          "text",
                          "usually plural "
                        ],
                        [
                          "vis",
                          [
                            {
                              "t": "He stood on the {it}balls{/it} of his feet."
                            }
                          ]
                        ]
                      ]
                    ]
                  ],
                  [
                    "text",
                    "{dx}see picture at {dxt|foot||}{/dx}"
                  ]
                ]
              }
            ]
          ],
          [
            [
              "sen",
              {
                "sn": "5",
                "sls": [
                  "informal + often offensive"
                ]
              }
            ],
            [
              "sense",
              {
                "sn": "a",
                "sgram": "count",
                "dt": [
                  [
                    "text",
                    "{bc}{sx|testicle||}"
                  ],
                  [
                    "uns",
                    [
                      [
                        [
                          "text",
                          "usually plural "
                        ],
                        [
                          "vis",
                          [
                            {
                              "t": "She kicked him in the {it}balls{/it}."
                            }
                          ]
                        ]
                      ]
                    ]
                  ]
                ]
              }
            ],
            [
              "sense",
              {
                "sn": "b",
                "bnote": "balls",
                "sgram": "plural",
                "dt": [
                  [
                    "text",
                    "{bc}the courage that is needed to do something "
                  ],
                  [
                    "vis",
                    [
                      {
                        "t": "You don't have the/enough {it}balls{/it} [={it}guts{/it}, {it}nerve{/it}] to fight me."
                      }
                    ]
                  ]
                ]
              }
            ],
            [
              "sense",
              {
                "sn": "c",
                "bnote": "balls",
                "sgram": "plural",
                "sls": [
                  "British"
                ],
                "dt": [
                  [
                    "text",
                    "{bc}{sx|nonsense||}"
                  ],
                  [
                    "uns",
                    [
                      [
                        [
                          "text",
                          "often used as an interjection to express disapproval or annoyance"
                        ]
                      ]
                    ]
                  ]
                ]
              }
            ]
          ],
          [
            [
              "sen",
              {
                "sn": "6",
                "sgram": "count"
              }
            ],
            [
              "sense",
              {
                "sn": "a",
                "sls": [
                  "sports"
                ],
                "dt": [
                  [
                    "text",
                    "{bc}a ball that is thrown or hit "
                  ],
                  [
                    "vis",
                    [
                      {
                        "t": "She hit a high arching {it}ball{/it} over the net."
                      },
                      {
                        "t": "I thought the {it}ball{/it} [=serve] was good, but my opponent said it was out."
                      }
                    ]
                  ],
                  [
                    "text",
                    "{dx}see also {dxt|air ball||} {dxt|curveball||} {dxt|fastball||} {dxt|fly ball||} {dxt|ground ball||} {it}fair ball{/it} at {dxt|fair:1||} {it}foul ball{/it} at {dxt|foul:1||}{/dx}"
                  ]
                ]
              }
            ],
            [
              "sense",
              {
                "sn": "b",
                "sls": [
                  "baseball"
                ],
                "dt": [
                  [
                    "text",
                    "{bc}a pitch that does not go through the proper area and that the batter does not swing at "
                  ],
                  [
                    "vis",
                    [
                      {
                        "t": "The first pitch was a {it}ball{/it} but the next two pitches were strikes."
                      }
                    ]
                  ]
                ]
              }
            ]
          ]
        ]
      }
    ],
    "dros": [
      {
        "drp": "carry the ball",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "US",
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}to have the responsibility for doing something "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "No one else is available to make the arrangements, so it's up to you to {it}carry the ball{/it}."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "drop the ball",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "US",
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}to make a mistake especially by not doing something important "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "I think the mayor {it}dropped the ball{/it} by not hiring more police officers."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "get/set/start the ball rolling",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}to begin an activity or process "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "She tried to {it}get the ball rolling{/it} by asking him a few questions."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "keep the ball rolling",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}to cause an activity or process to continue "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "I've started the preparations for the party, but it's up to you to {it}keep the ball rolling{/it}."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "keep your eye on the ball",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}to continue thinking about or giving attention to something important that you want to do or achieve "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "She really needs to {it}keep her eye on the ball{/it} [=stay focused] if she wants to win the election."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "on the ball",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sls": [
                      "informal"
                    ],
                    "dt": [
                      [
                        "text",
                        "{bc}mentally prepared {bc}aware of what is happening and ready to do what is needed or wanted "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "With so many intelligent students, the teacher must always be {it}on the ball{/it}."
                          },
                          {
                            "t": "Their lawyer was really {it}on the ball{/it}."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "play ball",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "sn": "1",
                    "dt": [
                      [
                        "text",
                        "{bc}to begin or continue to play a game with a ball (such as baseball) "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "{ldquo}Let's {it}play ball{/it}!{rdquo} shouted the umpire."
                          },
                          {
                            "t": "We went outside to {it}play{/it} some {it}ball{/it}."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ],
              [
                [
                  "sense",
                  {
                    "sn": "2",
                    "dt": [
                      [
                        "text",
                        "{bc}to do what other people want you to do {bc}to cooperate or work with other people "
                      ],
                      [
                        "vis",
                        [
                          {
                            "t": "He refused to {it}play ball{/it} with the police."
                          }
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      },
      {
        "drp": "the ball is in your court",
        "def": [
          {
            "sseq": [
              [
                [
                  "sense",
                  {
                    "dt": [
                      [
                        "snote",
                        [
                          [
                            "t",
                            "If {it}the ball is in your court{/it}, you are the person who is expected or required to do something."
                          ],
                          [
                            "vis",
                            [
                              {
                                "t": "What do you think we should do now? {it}The ball is in your court{/it}."
                              },
                              {
                                "t": "She's waiting for {it}the ball to be in her court{/it}."
                              }
                            ]
                          ]
                        ]
                      ]
                    ]
                  }
                ]
              ]
            ]
          }
        ]
      }
    ],
    "dxnls": [
      "compare {dxt|ball:3||}"
    ],
    "artl": [
      {
        "artid": "ball_rev.eps",
        "dim": "191,288"
      }
    ],
    "shortdef": [
      "a usually round object that is used in a game or sport or as a toy",
      "something that has a round shape",
      "a round bullet shot out of an old-fashioned gun"
    ]
  },

Pojos

I use dictionary to hold a meta object, that hold's a appShortDef object.

Dicionario

package com.ankitoword.entity;

public class Dicionario {
    private Meta meta;

    public Meta getMeta() {
      return meta;
    }

    public void setMeta(Meta meta) {
      this.meta = meta;
    } 
}

Meta

public class Meta {

    private String id;
    
    @JsonProperty(value="app-shortdef")
    private AppShortDef appShortdef;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public AppShortDef getAppShortdef() {
        return appShortdef;
    }

    public void setAppShortdef(AppShortDef appShortdef) {
        this.appShortdef = appShortdef;
    }
}

AppShortDef public class AppShortDef {

    public String hw;
    public String fl;
    public String[] def;
    
    public String getHw() {
        String[] split = hw.split(":");
        return split[0];
    }

    public void setHw(String hw) {
        this.hw = hw;
    }

    public String getFl() {
        return fl;
    }

    public void setFl(String fl) {
        this.fl = fl;
    }

    public String[] getDef() {
        return def;
    }

    public void setDef(String[] def) {
        this.def = def;
    }    
}

Solution

  • Your “normal” response isn’t valid JSON, but that aside, here’s what you can do. Get the response content as a string with bodyToMono(String.class). Then read the response as a JSON tree

    JsonNode root = mapper.readTree(jsonString)
    if (root.isArray())
        // deserialize into a list
    else
        // deserialize into the meta structure
    

    You can convert a JsonNode to an object using mapper.treeToValue.