首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Java 11 HttpClient反序列化JSON,使用JSON停止自定义BodyHandler,并且不会继续

使用Java 11 HttpClient反序列化JSON,使用JSON停止自定义BodyHandler,并且不会继续
EN

Stack Overflow用户
提问于 2019-08-23 15:41:43
回答 3查看 18.4K关注 0票数 17

在直接使用带有自定义HttpClient::send的Java11 HttpResponse.BodyHandler将JSON反序列化为定制对象时,我遇到了问题。我在回答这个问题时遇到了这个问题。

我正在使用的版本:

  • OpenJDK 11
  • 杰克逊2.9.9.3

我创建了一个简单的泛型JsonBodyHandler类,它实现了HttpResponse.BodyHandler

代码语言:javascript
运行
复制
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方法定义为:

代码语言:javascript
运行
复制
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的映射来测试它:

代码语言:javascript
运行
复制
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类:

代码语言:javascript
运行
复制
public class Model {
        private String userId;
        private String id;
        private String title;
        private boolean completed;


    //getters setters constructors toString
}

产出与预期相符:

代码语言:javascript
运行
复制
Model{userId='1', id='1', title='delectus aut autem', completed=false}

但是,当我首先将asJSON方法更改为读取InputStream而不是String时:

代码语言:javascript
运行
复制
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),但是它只是挂起。有人知道有什么问题吗?

EN

Stack Overflow用户

发布于 2021-09-16 15:23:49

通过使用杰克逊TypeReference,我能够单独使用泛型来实现它,而不需要冗余的Class<T>参数。

代码语言:javascript
运行
复制
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();
    }

}

并在使用中

代码语言:javascript
运行
复制
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();
    }
}
票数 5
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57629401

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档