Henrique
Henrique

Reputation: 221

How can I decode a response as a list?

I receive this response:

[{"id":1,"someField":"someValue"}]

Here is my request:

private HttpRequest doRequest(String body, URI uri) {
    return HttpRequest.newBuilder()
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .uri(uri)
            .headers(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
            .build();
}

and I tried to do this, but, it didn't work:

protected ClassToDecode createResponse(HttpResponse<HttpBodyCodec> response) {
    return response.body().decodeAs(ClassOfResponse.class);
}

My ClassToDecode has a list of my response class:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@EqualsAndHashCode
public class ClassToDecode {
    private List<ClassResponse> responses;
}

and my ClassResponse with the fields to decode:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
@EqualsAndHashCode
public class ClassResponse  {

  @JsonProperty("id")
  private Integer id = null;

  @JsonProperty("someField")
  private String someField = null;

}

Doing this way, the fields are not filled with the response. I'm not able to decode the list I receive, how should I do it?

Upvotes: 1

Views: 1489

Answers (3)

Henrique
Henrique

Reputation: 221

These above answers are right. But, I solved this problem in this way:

protected List<ClassToDecode> createResponse(HttpResponse<HttpBodyCodec> response) {
    return response.body().decodeAs(new TypeRef<>() { });
}

Just another way to solve.

Upvotes: 0

Marco
Marco

Reputation: 587

the reason why your class ClassToDecode doesn't work is because it's trying to find the key responses into the the json object, something like this:

{"responses":[{"id":1,"someField":"someValue"}]}

the easiest way to do what you want is:

public class ClassToDecode extends ArrayList<ClassResponse> {
}

This should we work, and help you to decode.

regards.

Upvotes: 2

Haakon L&#248;tveit
Haakon L&#248;tveit

Reputation: 1037

What you're trying to do doesn't really work as is, because:

  • Jackson sees a JSON type that is a list/array of things.
  • Jackson does not see a list that it can deserialize to. Only a thing that has a list. This is a crucial difference.

You have several options.

  1. You have what Marco suggested, which turns your ClassToDecode into a list. (There's also AbstractList if you want to get really fancy, I think Marco's suggestions is better, since you don't have to add any logic for a one-off class.) I think this is a good suggestion if you need to deserialize to that specific class.

  2. You can just have a List instead of ClassToDecode. If you don't have anything special in the class, this is good enough. But it may not be. You can of course also just new ClassToDecode(deserializedJsonList) later if you need to. If you just need an object for deserialization this is probably your best bet.

  3. If you control the JSON sent out, you can have the list in a field called responses, as Marco pointed out. This way your objectmapper should be able to deal with things.

  4. You can use a custom deserializer to deserialize lists. But that is as we say, shooting sparrows with artillery.

Upvotes: 1

Related Questions