Pertanyaan Mengkonsumsi objek JSON di layanan Jersey


Saya telah mencari-cari solusi untuk mengetahui cara melakukan ini: Saya memiliki layanan Jersey REST. Permintaan yang memanggil layanan REST berisi objek JSON. Pertanyaan saya adalah, dari implementasi metode Jersey POST, bagaimana saya bisa mendapatkan akses ke JSON yang ada di tubuh permintaan HTTP?

Setiap tips, trik, pointer ke kode sampel akan sangat dihargai.

Terima kasih...

--Steve


32
2017-11-02 17:08


asal


Jawaban:


Saya tidak yakin bagaimana Anda akan mendapatkan string JSON itu sendiri, tetapi Anda pasti bisa mendapatkan data yang dikandungnya sebagai berikut:

Tentukan kelas Java JAXB beranotasi (C) yang memiliki struktur yang sama dengan objek JSON yang sedang diteruskan pada permintaan.

misalnya untuk pesan JSON:

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

Gunakan sesuatu seperti:

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

Kemudian, Anda dapat menentukan metode di kelas sumber daya Anda dengan parameter tipe C. Ketika Jersey memanggil metode Anda, objek JAXB akan dibuat berdasarkan objek POSTed JSON.

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

11
2017-11-02 17:48



Seperti yang sudah disarankan, mengubah @Consumes Jenis-Konten ke text/plain akan berfungsi, tetapi tampaknya tidak benar dari sudut pandang REST API.

Bayangkan pelanggan Anda harus POST JSON ke API Anda tetapi perlu menentukan header Content-Type sebagai text/plain. Tidak bersih menurut saya. Dalam istilah sederhana, jika API Anda menerima JSON maka header permintaan harus menentukan Content-Type: application/json.

Untuk menerima JSON tetapi membuat serial ke dalam String objek daripada POJO Anda dapat menerapkan kebiasaan MessageBodyReader. Melakukannya dengan cara ini sama mudahnya, dan Anda tidak perlu berkompromi pada spesifikasi API Anda.

Ada baiknya membaca dokumen untuk MessageBodyReader sehingga Anda tahu persis cara kerjanya. Beginilah cara saya melakukannya:

Langkah 1. Menerapkan kebiasaan 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);
  }
}

Konsep dasar di atas adalah untuk memeriksa apakah aliran input diharapkan dikonversi menjadi a String (ditentukan oleh Type genericType). Jika demikian, maka cukup masukkan JSON ke yang ditentukan type (yang akan menjadi a String). Jika jenis yang diharapkan adalah semacam POJO, kemudian gunakan pustaka JSON (misalnya Jackson atau GSON) untuk deserialize ke POJO.

Langkah 2. Mengikat Anda MessageBodyReader

Ini tergantung pada kerangka kerja apa yang Anda gunakan. Saya menemukan bahwa Guice dan Jersey bekerja sama dengan baik. Begini cara saya mengikat saya MessageBodyReader di Guice:

Di dalam saya JerseyServletModule Saya mengikat pembaca seperti itu -

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

Di atas CustomJsonReader akan deserialize muatan JSON ke POJO juga, jika Anda hanya ingin JSON mentah, String objek.

Manfaat melakukannya dengan cara ini adalah ia akan menerimanya Content-Type: application/json. Dengan kata lain, penangan permintaan Anda dapat disetel untuk menggunakan JSON, yang tampaknya tepat:

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

15
2018-02-07 12:23



Jersey mendukung akses tingkat rendah ke JSONObject yang diolah menggunakan JettObject JSONOjject dan JSONArray.

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

Sebagai contoh:

{
  "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;
}

Lihat Dokumentasi Jersey untuk lebih banyak contoh.


11
2018-04-26 14:40



Ini memberi Anda akses ke pos mentah.

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

6
2018-06-12 13:20



Kirim / POST formulir / HTTP.POST dengan parameter dengan JSON sebagai nilainya.

@QueryParam jsonString

desolveJson publik (jsonString)


0
2017-11-02 20:23