leonixyz
leonixyz

Reputation: 1192

Mapping all `@QueryParam` to `JSON` data structure

I'm trying to map all @QueryParam of my JAX-RS Jersey application to a JSON data structure as follows:

@GET
@Produces("application/json")
@Path("/submit")
public String submit(@Context UriInfo info) {
    MultivaluedMap<String, String> params = info.getQueryParameters();

    JSONObject toInsert = new JSONObject();
    toInsert.accumulate("id", params.get("id").get(0));
    toInsert.accumulate("user", params.get("user").get(0));

    //params.remove("id");      have also like to delete these two
    //params.remove("user");    to avoid having duplicates in
    //                          the next rows

    JSONArray questions = new JSONArray();
    for (Entry<String, List<String>> entry : params.entrySet()){
        String[] values = (String[]) entry.getValue().toArray();
        String key = entry.getKey();
        questions.put(key, values);

    } 

    toInsert.accumulate("questions", questions);

    return toInsert;
}

Unfortunately I get an Exception

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
rest.Forms.submit(Forms.java:195)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:406)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:350)
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:320)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:219)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

I also tried the following after reading this, it doesn't throw an exception but the result is semantically wrong. If I substitute the inner for loop as follows:

    for (Entry<String, List<String>> entry : params.entrySet()){
        List<String> values = entry.getValue();
        String key = entry.getKey();
        Object[] objectArray = values.toArray();
        questions.put(key, Arrays.copyOf(objectArray, objectArray.length, String[].class));
    } 

The result in this case is composed in the "questions" part only as the list of keys, and I also want the associated values. Thank you in advance

{ "id" : "f5475dc0-c8ce-11e3-9c1a-0800200c9a66",
  "questions" : [ "id",
      "l_name",
      "f_name",
      "citizenship",
      "like",
      "user"
    ],
  "user" : "gigi"
}

Upvotes: 1

Views: 779

Answers (1)

azurefrog
azurefrog

Reputation: 10945

You can't actually cast the output of toArray() in that fashion. You need to supply the type to the toArray() call so that it returns an array of the appropriate type.

For instance:

    List<String> list = new ArrayList<String>();
    list.add("foo");
    list.add("bar");
    String[] arr1 = (String[]) list.toArray(); // this throws a ClassCastException
    String[] arr2 = list.toArray(new String[0]); // this works

You just need to replace this line

        String[] values = (String[]) entry.getValue().toArray();

with this one

        String[] values = entry.getValue().toArray(new String[0]);

and your code should work.

Upvotes: 1

Related Questions