如何通过 REST 传输 ArrayList<Map>?

How can I transfer an ArrayList<Map> via REST?

编辑: 我尝试实施@Durgpal Singh 和@Nikhil 的建议。我更改了代码,使其看起来像这样。

客户:

    Client client = ClientBuilder.newClient();
    WebTarget target = client
            .target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));

    Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
    Response response = invocationBuilder.get();

Map<String, List<Map>> result_ = response.readEntity(new GenericType<Map<String, List<Map>>>() { });
result = (ArrayList<Map>) result_.get("data");

服务器:

ArrayList<Map> result;

result = new Ls3Algorithm().execute(new File("petrinetze").getAbsolutePath(), k, theta);

Map<String, List<Map>> map = new HashMap<>();
map.put("data", result);        
return Response.ok(map).build();

不幸的是,这会导致 Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<java.lang.String, java.util.List<java.util.Map>>.

我哪里出错了?

--------------------------------

我是 RESTful Web 服务的新手,目前正在编写一个提供计算算法的微服务。我正在测试下面发布的服务。

工作流程: 客户端将一些数据保存在 MongoDB 数据库中,并通过 @PathParam 发送相关文件的名称作为 GET 请求的一部分。然后服务器从 MongoDB 中检索文件,处理其算法并将结果作为 List<Map> 打包在 Response 对象中发送回。

目标: 将结果 (List<Map>) 传输为 JSON 并在客户端控制台上打印出来。

客户:

package ls3test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Map;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;

public class Ls3TransmissionTest {
    final static String petrinets = "eins, zwei, drei, vier";
    final static int k = 3;
    final static float theta = 0.9f;

    public static void main(String[] args) throws IOException {

        [... save all the relevant files in the MongoDB ...]    

        ArrayList<Map> result = new ArrayList<Map>();

        Client client = ClientBuilder.newClient();
        WebTarget target = client
                .target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));

        Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
        Response response = invocationBuilder.get();

        result = response.readEntity(new GenericType<ArrayList<Map>>() {
        });

        ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
        String json = ow.writeValueAsString(result);
        }
}

服务器:

package service;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

@SuppressWarnings("deprecation")
@Path("/ls3algorithm")
public class Resource {

    // SLF4J is provided with Dropwizard
    Logger log = LoggerFactory.getLogger(Resource.class);

    @SuppressWarnings("rawtypes")
    @GET
    @Path("/{petrinets}/{k}/{theta}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response ls3execute(@PathParam("petrinets") String petrinetNames, @PathParam("k") int k,
            @PathParam("theta") float theta) {

        [... get all the relevant files from the MongoDB ...]

        List<Map> result;
        Ls3Algorithm ls3Algorithm = new Ls3Algorithm();

        result = ls3Algorithm.execute(new File("petrinetze").getAbsolutePath(), k, theta);

        GenericEntity<List<Map>> entity = new GenericEntity<List<Map>>(result) {};
        Response response = Response.ok(entity).build();

        return response;
    }
}

这是行不通的,我收到的异常如下:

Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.ArrayList<java.util.Map>.
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:231)
    at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
    at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:834)
    at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
    at org.glassfish.jersey.client.InboundJaxrsResponse.call(InboundJaxrsResponse.java:126)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
    at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:267)
    at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:123)
    at ls3test.Ls3TransmissionTest.main(Ls3TransmissionTest.java:89)

Ls3TransmissionTest.java:89ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();

我现在花了很多时间研究这个问题,但我找不到真正适合它的例子。我想念什么?非常感谢任何帮助或提示!

不明白为什么需要用 GenericEntity 包装 List。像下面这样简单的东西会起作用:-

@SuppressWarnings("rawtypes")
@GET
@Path("/{petrinets}/{k}/{theta}")
@Produces(MediaType.APPLICATION_JSON)
public Response ls3execute(@PathParam("petrinets") String petrinetNames, @PathParam("k") int k,
        @PathParam("theta") float theta) {

    //[... get all the relevant files from the MongoDB ...]

    List<Map> result;
    Ls3Algorithm ls3Algorithm = new Ls3Algorithm();

    result = ls3Algorithm.execute(new File("petrinetze").getAbsolutePath(), k, theta);

    Response response = Response.ok(result).build();

    return response;
}

在客户端,

    String result = response.readEntity(String.class);
    return result;

你可以发一张地图。像这样

Map<String, Object> map = new HashMap<>();
map.put("data", entity);
Response.ok(map).build();
return Response;