在直接使用带有自定义HttpClient::send的Java11 HttpResponse.BodyHandler将JSON反序列化为定制对象时,我遇到了问题。我在回答这个问题时遇到了这个问题。
我正在使用的版本:
我创建了一个简单的泛型JsonBodyHandler类,它实现了HttpResponse.BodyHandler。
public class JsonBodyHandler<W> implements HttpResponse.BodyHandler<W> {
    private final Class<W> wClass;
    public JsonBodyHandler(Class<W> wClass) {
        this.wClass = wClass;
    }
    @Override
    public HttpResponse.BodySubscriber<W> apply(HttpResponse.ResponseInfo responseInfo) {
        return asJSON(wClass);
    }
}asJSON方法定义为:
public static <W> HttpResponse.BodySubscriber<W> asJSON(Class<W> targetType) {
        HttpResponse.BodySubscriber<String> upstream = HttpResponse.BodySubscribers.ofString(StandardCharsets.UTF_8);
        return HttpResponse.BodySubscribers.mapping(
                upstream,
                (String body) -> {
                    try {
                        ObjectMapper objectMapper = new ObjectMapper();
                        return objectMapper.readValue(body, targetType);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
            });
}因此,它返回一个自定义HttpResponse.BodySubscriber,它将主体作为String,然后应用从JSON到给定的targetType的映射来测试它:
public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        HttpRequest request = HttpRequest.newBuilder(new URI("https://jsonplaceholder.typicode.com/todos/1"))
                .header("Accept", "application/json")
                .build();
        Model model = HttpClient.newHttpClient()
                .send(request, new JsonBodyHandler<>(Model.class))
                .body();
        System.out.println(model);
}Model类:
public class Model {
        private String userId;
        private String id;
        private String title;
        private boolean completed;
    //getters setters constructors toString
}产出与预期相符:
Model{userId='1', id='1', title='delectus aut autem', completed=false}但是,当我首先将asJSON方法更改为读取InputStream而不是String时:
public static <W> HttpResponse.BodySubscriber<W> asJSON(Class<W> targetType) {
    HttpResponse.BodySubscriber<InputStream> upstream = HttpResponse.BodySubscribers.ofInputStream();
    return HttpResponse.BodySubscribers.mapping(
                upstream,
                (InputStream is) -> {
                    try (InputStream stream = is) {
                        ObjectMapper objectMapper = new ObjectMapper();
                        return objectMapper.readValue(stream, targetType);
                    } catch (IOException e) {
                        throw new UncheckedIOException(e);
                    }
            });
}它在使用ObjectMapper调用该值后挂起,并且不继续(我已经检查它是否成功地从端点获得响应,状态代码为200),但是它只是挂起。有人知道有什么问题吗?
发布于 2021-09-16 15:23:49
通过使用杰克逊TypeReference,我能够单独使用泛型来实现它,而不需要冗余的Class<T>参数。
package com.company;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.http.HttpResponse;
import java.util.function.Supplier;
public class JsonBodyHandler<W> implements HttpResponse.BodyHandler<Supplier<W>> {
    public JsonBodyHandler() {
    }
    private static <W> Supplier<W> toSupplierOfType(InputStream inputStream) {
        return () -> {
            try (InputStream stream = inputStream) {
                return new ObjectMapper().readValue(stream, new TypeReference<W>() {
                });
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    }
    private static <W> HttpResponse.BodySubscriber<Supplier<W>> asJSON() {
        return HttpResponse.BodySubscribers.mapping(
                HttpResponse.BodySubscribers.ofInputStream(),
                JsonBodyHandler::toSupplierOfType);
    }
    @Override
    public HttpResponse.BodySubscriber<Supplier<W>> apply(HttpResponse.ResponseInfo responseInfo) {
        return JsonBodyHandler.asJSON();
    }
}并在使用中
package com.company;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.time.Duration;
import java.util.List;
public class Main {
    private static final HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://myApi"))
            .timeout(Duration.ofMinutes(1))
            .header("Content-Type", "application/json")
            .build();
    private static final HttpClient client = HttpClient.newBuilder().build();
    public static void main(String[] args) throws InterruptedException {
        client.sendAsync(Main.request, new JsonBodyHandler<List<MyDto>>())
                .thenAccept(response -> {
                    List<MyDto> myDtos = response.body().get();
                    System.out.println(myDtos);
                }).join();
    }
}https://stackoverflow.com/questions/57629401
复制相似问题