I'm trying to send a POST request to a server, get the response, and parse it (it is a JSON file).
I am using Unirest for my POST request, simply as below:
HttpResponse<JsonNode> response = Unirest
.post("http://myserver.com/file")
.header("cache-control", "no-cache")
.header("Postman-Token", "02ec2fa1-afdf-4a2a-a535-353424d99400")
.header("Content-Type", "application/json")
.body("{some JSON body}")
.asJson();
// retrieve the parsed JSONObject from the response
JSONObject myObj = response.getBody().getObject();
// extract fields from the object
String msg = myObj.toString();
System.out.println(msg);
But I have problems getting the raw JSON text (I want to use JSONPath to parse the response).
How can I do that? All my attempts calling toString() methods failed so far.
The Unirest API supports this out of the box - Use asString() instead of asJson() to get the response as HttpResponse<String>.
HttpResponse<String> response = Unirest
.post("http://myserver.com/file")
.header("cache-control", "no-cache")
.header("Postman-Token", "02ec2fa1-afdf-4a2a-a535-353424d99400")
.header("Content-Type", "application/json")
.body("{some JSON body}")
.asString();
System.out.println(response.getBody());
You can do it like this:
InputStream inputStream = response.getRawBody();
BufferedInputStream bis = new BufferedInputStream(inputStream);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
int result = bis.read();
while(result != -1) {
buf.write((byte) result);
result = bis.read();
}
String rawJson = buf.toString("UTF-8");
Related
I'm writting an Java application that do requests through REST API to Named Entity Recognition service (deeppavlov) running in a local network.
So I request data by following:
String text = "Welcome to Moscow, John";
List<String> textList = new ArrayList<String>();
textList.add(text);
JSONObject json = new JSONObject();
json.put("x", textList);
String URL = "http://localhost:5005/model";
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(URL))
.header("accept", "application/json")
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(json.toString()))
.build();
try {
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.body());
System.out.println(response.body().getClass());
} catch (IOException | InterruptedException e) {
}
As result I get:
[[["Welcome","to","Moscow",",","John"],["O","O","B-GPE","O","B-PERSON"]]]
class java.lang.String
It is a string and I don't know how to convert it to object, array, map or list to iterate through. Please help.
It depends from the library that you are using to deserialize the string.
It seems that you are using org json code, so a possible solution uses a JSONTokener:
Parses a JSON (RFC 4627) encoded string into the corresponding object
and then use the method nextValue:
Returns the next value from the input. Can be a JSONObject, JSONArray, String, Boolean, Integer, Long, Double or JSONObject#NULL.
The code will be the following
Object jsonObject = new JSONTokener(jsonAsString).nextValue();
I am doing some actions on a Response body after changing it to String:
Response myResponse = get(Some Endpoint);
String res = getIncidentResponse.getBody().asString();
//Some operations on the String
How to change back this "res" String to Response ?
Here is the conversion of String to Object.
ObjectMapper objm = new ObjectMapper();
Response response = objm.readValue(string, Response.class);
This should work!
I'm trying to get some json data using OkHttp and can't figure out why when i try logging the response.body().toString() what i get is Results:﹕ com.squareup.okhttp.Call$RealResponseBody#41c16aa8
try {
URL url = new URL(BaseUrl);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.header(/****/)
.build();
Call call = client.newCall(request);
Response response = call.execute();
**//for some reason this successfully prints out the response**
System.out.println("YEAH: " + response.body().string());
if(!response.isSuccessful()) {
Log.i("Response code", " " + response.code());
}
Log.i("Response code", response.code() + " ");
String results = response.body().toString();
Log.i("OkHTTP Results: ", results);
I don't know what i'm doing wrong here. How do i get the response string?
You have use .string() function to print the response in System.out.println(). But at last in Log.i() you are using .toString().
So please use .string() on response body to print and get your request's response, like:
response.body().string();
NOTE:
.toString(): This returns your object in string format.
.string(): This returns your response.
I think this solve your problem... Right.
Just in case someone bumps into the same weird thing as I have. I run my code during development in Debug Mode and apparently since OKHttp 2.4
..the response body is a one-shot value that may be consumed only once
So when in debug there is a call "behind the scene" from the inspector and the body is always empty. See: https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html
The response.body.string() can be consumed only once.
Please use as below:
String responseBodyString = response.body.string();
Use the responseBodyString as needed in your application.
Given that a response can potentially produce an OutOfMemoryError in cases of large files, you can instead "peek" the body with the number of bytes and call the string() method.
Note that this will consume the body.
response.peekBody(500).string());
Following is my modified CurlInterceptor. Check the end of the intercept function where I m recreating the Response object after consuming the old Response.
var responseBodyString = responseBody?.string()
response = response.newBuilder()
.body(
ResponseBody.create(
responseBody?.contentType(),
responseBodyString.toByteArray()
)
)
.build()
class CurlInterceptor: Interceptor
{
var gson = GsonBuilder().setPrettyPrinting().create()
override fun intercept(chain: Interceptor.Chain): Response {
Timber.d(" **** ->>Request to server -> ****")
val request = chain.request()
var response = chain.proceed(request)
var curl = "curl -v -X ${request.method()}"
val headers = request.headers()
for ( i in 0..(headers.size() -1) ){
curl = "${curl} -H \"${headers.name(i)}: ${headers.value(i)}\""
}
val requestBody = request.body()
if (requestBody != null) {
val buffer = Buffer()
requestBody.writeTo(buffer)
var charset: Charset =
Charset.forName("UTF-8")
curl = "${curl} --data '${buffer.readString(charset).replace("\n", "\\n")}'"
}
Timber.d("$curl ${request.url()}")
Timber.d("response status code ${response.code()} message: ${response.message()}")
dumbHeaders(response)
var responseBody = response?.body()
if(responseBody != null )
{
var responseBodyString = responseBody?.string()
response = response.newBuilder()
.body(
ResponseBody.create(
responseBody?.contentType(),
responseBodyString.toByteArray()
)
)
.build()
responseBodyString = gson.toJson(responseBodyString)
Timber.d("response json -> \n $responseBodyString")
}
Timber.d(" **** << Response from server ****")
return response
}
fun dumbHeaders(response: Response) {
try {
if (response.headers() != null) {
for (headerName in response.headers().names()) {
for (headerValue in response.headers(headerName)) {
Timber.d("Header $headerName : $headerValue")
}
}
}
}
catch (ex: Exception){}
}
}
Instead of using .toString() which returns an object
String results = response.body().toString();
you can use
String results = response.body().string();
Call call = client.newCall(request);
return call.execute().body().string();
we can get response as a return fromby these
try to change it like that for example:
protected String doInBackground(String... params) {
try {
JSONObject root = new JSONObject();
JSONObject data = new JSONObject();
data.put("type", type);
data.put("message", message);
data.put("title", title);
data.put("image_url", imageUrl);
data.put("uid",uid);
data.put("id", id);
data.put("message_id", messageId);
data.put("display_name", displayName);
root.put("data", data);
root.put("registration_ids", new JSONArray(receipts));
RequestBody body = RequestBody.create(JSON, root.toString());
Request request = new Request.Builder()
.url(URL)
.post(body)
.addHeader("Authorization", "key=" + serverKey)
.build();
Response response = mClient.newCall(request).execute();
String result = response.body().string();
Log.d(TAG, "Result: " + result);
return result;
} catch (Exception ex) {
Log.e(TAG,"Exception -> "+ex.getMessage());
}
return null;
}
Recreate the response object after consuming the string
val responseBodyString = response.body()!!.string()
response = response.newBuilder()
.body(ResponseBody.create(responseBody?.contentType(), responseBodyString.toByteArray()))
.build()
Kotlin Programmers I am here for you
response.body?.charStream()?.readText()?.let {
//Where it refers to Response string
callBack.onAPISuccess(it)
}
Here you can not use .toString() function and .string() function is not available in Kotlin than you can user charStream() and than convert that charStream into readText() but you have to unwrap the whole value before passing it.But it will never create problem.
I have not explored these charStream() and readText() functions in java but I think it should be there and you can use this in java if these functions are available because I just got to know that java has deprecated the .string() function.
I have
HttpResponse response = httpclient.execute(httpget);
my method can transfer byte[] over sockets on device and PC, so how can i convert HttpResponse into byte[] and than back to HttpResponse?
It is not easy.
If you simply wanted the body of the response, then you could do this to grab it
ByteArrayOutputStream baos = new ByteArrayOutputStream();
response.getEntity().writeTo(baos);
byte[] bytes = baos.toByteArray();
Then you could add the content to another HttpResponse object as follows:
HttpResponse response = ...
response.setEntity(new ByteArrayEntity(bytes));
But that's probably not good enough because you most likely need all of the other stuff in the original response; e.g. the status line and the headers (including the original content type and length).
If you want to deal with the whole response, you appear to have two choices:
You could pick the response apart (e.g. getting the status line, iterating the headers) and manually serialize, then do the reverse at the other end.
You can use HttpResponseWriter to do the serializing and HttpResponseParser to rebuild the response at the other end. This is explained here.
you need to get it as a stream: response.getEntity().getContent()
then you can directly read the stream into a byte[].
With java11:
var client = HttpClient.newBuilder().build();
var request = HttpRequest.newBuilder()
.uri(URI.create("https://yourdomain.test")).GET().build();
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
if (200 == response.statusCode()) {
byte[] bytes = response.body();
}
I receive a post request from client. This request contains some json data which I want to part on the server side. I have created the server using httpcore. HttpRequestHandler is used for handling the request. Here is the code I thought would work
HttpEntity entity = ((HttpEntityEnclosingRequest)request).getEntity();
InputStream inputStream = entity.getContent();
String str = inputStream.toString();
System.out.println("Post contents: " + str);*/
But I cant seem to find a way to get the body of the request using the HttpRequest object. How can I extract the body from the request object ? Thanks
You should use EntityUtils and it's toString method:
String str = EntityUtils.toString(entity);
getContent returnes stream and you need to read all data from it manually using e.g. BufferedReader. But EntityUtils does it for you.
You can't use toString on stream, because it returns string representation of the object itself not it's data.
One more thing: AFAIK GET requests can't contain body so it seems you get POST request from client.
... and for MultipartEntity use this:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
entity.writeTo(baos);
} catch (IOException e) {
e.printStackTrace();
}
String text = new String(baos.toByteArray());