Question

J'ai été googler mon bout en essayant de savoir comment faire ceci: J'ai un service Jersey REST. La demande qui invoque le service REST contient un objet JSON. Ma question est, de la mise en œuvre de la méthode POST Jersey, comment puis-je avoir accès à l'JSON qui est dans le corps de la requête HTTP?

Les conseils, des astuces, conseils pour un exemple de code serait grandement apprécié.

Merci ...

- Steve

Était-ce utile?

La solution

Je ne sais pas comment vous obtenez à la chaîne JSON elle-même, mais vous pouvez certainement obtenir les données qu'il contient comme suit:

Définir une classe Java JAXB annoté (C) qui a la même structure que l'objet JSON qui est passé sur la demande.

par exemple. pour un message JSON:

{
  "A": "a value",
  "B": "another value"
}

Utilisez quelque chose comme:

@XmlAccessorType(XmlAccessType.FIELD)
public class C
{
  public String A;
  public String B;
}

Ensuite, vous pouvez définir une méthode dans votre classe de ressource avec un paramètre de type C. Lorsque Jersey appelle votre méthode, l'objet JAXB sera créé à partir de l'objet JSON ci-dessous.

@Path("/resource")
public class MyResource
{
  @POST
  public put(C c)
  {
     doSomething(c.A);
     doSomethingElse(c.B);
  }
}

Autres conseils

Comme nous l'avons suggéré, en changeant le type de contenu de @Consumes à text/plain fonctionnera, mais il ne semble pas juste d'un point de vue de l'API REST.

Imaginez votre client d'avoir à POST JSON à votre API, mais avoir besoin de spécifier l'en-tête Content-Type comme text/plain. Ce n'est pas propre à mon avis. En termes simples, si votre API accepte JSON alors l'en-tête de demande doit préciser Content-Type: application/json.

Pour accepter JSON, mais sérialisation dans un objet String plutôt qu'un POJO vous pouvez implémenter une coutume MessageBodyReader . En procédant ainsi, est tout aussi facile, et vous ne serez pas à faire des compromis sur vos spécifications API.

Il vaut la peine de lire la documentation MessageBodyReader si vous savez exactement comment cela fonctionne. Voici comment je l'ai fait:

Étape 1. Mettre en œuvre une coutume MessageBodyReader

@Provider
@Consumes("application/json")
public class CustomJsonReader<T> implements MessageBodyReader<T> {
  @Override
  public boolean isReadable(Class<?> type, Type genericType,
      Annotation[] annotations,MediaType mediaType) {
    return true;
  }

  @Override
  public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
      MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
      InputStream entityStream) throws IOException, WebApplicationException {

    /* Copy the input stream to String. Do this however you like.
     * Here I use Commons IOUtils.
     */
    StringWriter writer = new StringWriter();
    IOUtils.copy(entityStream, writer, "UTF-8");
    String json = writer.toString();

    /* if the input stream is expected to be deserialized into a String,
     * then just cast it
     */
    if (String.class == genericType)
      return type.cast(json);

    /* Otherwise, deserialize the JSON into a POJO type.
     * You can use whatever JSON library you want, here's
     * a simply example using GSON.
     */
    return new Gson().fromJson(json, genericType);
  }
}

Le concept de base ci-dessus est de vérifier si le flux d'entrée est prévu pour être converti en un String (spécifié par Type genericType). Si oui, alors tout simplement jeter le JSON dans le type spécifié (qui sera un String). Si le type attendu est une sorte de POJO, puis utilisez une bibliothèque JSON (par exemple Jackson ou GSON) désérialiser à un POJO.

Étape 2. Bind votre MessageBodyReader

Cela dépend de ce cadre que vous utilisez. Je trouve que Guice et Jersey travaillent bien ensemble. Voici comment je lie mon MessageBodyReader Guice:

Dans mon JerseyServletModule Je lie le lecteur comme si -

bind(CustomJsonReader.class).in(Scopes.SINGLETON);

Le CustomJsonReader ci-dessus désérialiser JSON charges utiles dans POJO, ainsi que, si vous voulez simplement la JSON brute, objets String.

L'avantage de le faire de cette façon est qu'il acceptera Content-Type: application/json. En d'autres termes, votre gestionnaire de requêtes peut être réglé à consommer JSON, qui semble approprié:

@POST
@Path("/stuff")
@Consumes("application/json") 
public void doStuff(String json) {
  /* do stuff with the json string */
  return;
}

Jersey soutient l'accès à faible niveau à l'aide des JSONObject analysé les types JETTISON JSONObject et JSONArray.

<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.8</version>
</dependency>

Par exemple:

{
  "A": "a value",
  "B": "another value"
}


@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON) 
public void doStuff(JSONObject json) {
  /* extract data values using DOM-like API */
  String a = json.optString("A");
  Strong b = json.optString("B");
  return;
}

Voir la documentation Jersey pour plus d'exemples.

Cela vous donne accès au poste brut.

@POST
@Path("/")
@Consumes("text/plain") 
@Produces(MediaType.APPLICATION_JSON)
public String processRequset(String pData) {
    // do some stuff, 
    return someJson;
}

Soumettre / POST forme / HTTP.POST avec un paramètre avec le JSON en tant que valeur.

@QueryParam jsonString

desolveJson publique (jsonString)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top