How to print output json instead of byte[] when #EnableHypermediaSupport(type = {HAL}) and using WebTestClient - spring-hateoas

When I enable #EnableHypermediaSupport and change my WebTestClient to accept HAL+JSON as such
this.client.get()
.uri(uriBuilder ->
uriBuilder
.path("/api/person/{id}")
.build(1268882))
.accept(MediaTypes.HAL_JSON)
.exchange()
.expectStatus().isOk()
.expectHeader().contentType(MediaTypes.HAL_JSON)
.expectBody()
.consumeWith(p -> System.out.println("PAYLOAD " + p))
.jsonPath("$.id",1268882L).exists();
The test passes but instead of System.out.println ouputing json i get "164 bytes of content" as an example.
However, the default usage of WebTestClient where no HAL+JSON MediaType enabled prints out JSON Response with no problem.
How to print out JSON Response body?

Related

How to convert compact Json to pretty print codename one

I want to know how to convert a string of compact Json to pretty print so that I can parse it. I have searched for this question in stack overflow but it doesn't seem like anyone has asked it for codename one.
Right now I have a string of compact Json but it can not be parsed. This is the code:
String JsonData = "{\"document\":{ \"type\":\"PLAIN_TEXT\", \"content\":\"Ask not what your country can do for you, ask what you can do for your country.\" },\"encodingType\":\"UTF8\"}";
JsonResponse = Rest.
post("https://language.googleapis.com/v1/documents:analyzeSyntax?key=[API KEY").
jsonContent().
body(JsonData).
getAsJsonMap();
String JsonString = (JsonResponse.getResponseData()).toString();
JSONParser parser = new JSONParser();
Map<String, Object> results = null;
try {
results = parser.parseJSON(new StringReader(JsonString));
} catch (IOException e) {
e.printStackTrace();
System.out.println("fail");
}
System.out.println("results "+results);
But when I run this code I get a bunch of these responses:
[EDT] 0:0:3,269 - Expected null for key value while parsing JSON token at row: 1 column: 5 buffer: e
and
java.lang.NumberFormatException: For input string: "ee0"
How should I convert my string of compact Json (JsonString) to pretty print so that I can parse it? Alternatively, is there a way to directly parse the response (JsonResponse)?
Thank You
You are printing out a map not a JSON string as the JSON data is already parsed. If you just want to look at the network protocol for debugging the best way to do that is open the Network Monitor in the simulator where you will see all HTTP requests and can copy out the response body JSON.
However you can still convert a Map back to JSON using:
Log.p("results " + JSONParser.mapToJson(results));
Notice you should use Log.p() and Log.e() to log strings/exceptions as that would work better on the devices.

Jettison can not convert json string to json object when there is an element has empty string value

My application is using camel rest (2.15.2) to catch a POST json String and then uses jettison to convert to a JSON Object. It is working fine with normal request.
POST request: {"request"={"lname"="aaa", "fname"="bb"}}
1. String body = exchange.getIn().getBody(String.class);
2. JSONObject obj = new JSONObject(body);
When i debug, variable body = {request={lname=aaa, fname=bb}}.
And line 2 returns a JSONObject. so far so good
if we try to another the request:
{"request"={"lname"=" ", "fname"="aa"}}
then body = {request={lname= , fname=aa}}
line2 returns Exception.
Could you please help me to fix this issue: convert json string which contains element has empty value string to json object.
The above request is acceptable in my scenarios.
Error:
org.codehaus.jettison.json.JSONException: Missing value. at character
15 of {request={lname= , fname=aa}} at
org.codehaus.jettison.json.JSONTokener.syntaxError(JSONTokener.java:463)
at
org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:356)
at org.codehaus.jettison.json.JSONObject.(JSONObject.java:230)
at
org.codehaus.jettison.json.JSONTokener.newJSONObject(JSONTokener.java:412)
at
org.codehaus.jettison.json.JSONTokener.nextValue(JSONTokener.java:327)
at org.codehaus.jettison.json.JSONObject.(JSONObject.java:230)
at org.codehaus.jettison.json.JSONObject.(JSONObject.java:311)

How to send json string body for FakeRequest without using withJsonBody in Play framework v2.x?

I have play scala v2.3 application. I'm trying to create a controller test by sending json string with FakeRequest as below:
class ApplicationSpec extends Specification {
"Application" should {
"Create Bob Test" in new WithApplication {
val jsonStr = """{"text": "hi bob"}"""
val result = route(FakeRequest(POST, "/bob")
.withHeaders("Content-Type" -> "application/json")
.withBody(jsonStr)
).get
status(result) === OK
}
}
}
The controller:
object Application extends Controller {
def bob = Action.async { request =>
println("request.headers: " + request.headers)
println("request.body: " + request.body)
println("request.body.asJson: " + request.body.asJson)
request.body.asJson.map { json =>
// do something with the json
Future.successful(Ok)
}.getOrElse(Future.successful(BadRequest))
}
}
When I run the test, it's failed and this is what printed:
request.headers: ArrayBuffer((Content-Type,List(text/plain; charset=utf-8)))
request.body: AnyContentAsText({"text": "hi bob"})
request.body.asJson: None
So the Content-Type header sent is not application/json despite I have set the header with application/json. And probably because of that, the request.body.asJson returns None.
Anyone know how to solve this?
Note: I know I can use .withJsonBody(Json.parse(jsonStr)) on the FakeRequest and it will succeed, but with this way I can't send broken or invalid json string for negative test case since withJsonBody accepts JsValue which the json string must be converted first with Json.parse.
By default, the Content-Type header gets overridden by the framework. A workaround is given in the blog
In your case, this should work
route(FakeRequest(POST, "/bob", FakeHeaders(Seq(CONTENT_TYPE->Seq("application/json"))), jsonStr))(Writeable(_.getBytes, None)).get
For multiple tests, an implicit can be created in the beginning for the writable and it need not to be passed in every test:
implicit val wString: Writeable[String] = Writeable(_.getBytes, None)

JSON format results from HTTPBuilder GET changed between 0.5.2 and 0.6

We recently updated dependencies of a REST integration test which uses Groovy, HTTPBuilder, JSONAssert and Junit. When we went from HTTPBuilder 0.5.2 to 0.6 many of our tests failed.
We found that the format of the response changed due to a new "feature" in HTTPBuilder that provides "Automatic response parsing for registered content types".
Old, (0.5.2) format, expected response:
[
{
"name":"Portfolio_REST_Test01",
"description":"",
"referenceValueType":"Net Value",
"unitType":"SHARES",
"tags":[]
}
]
New (0.6.2) format of response:
[{tags=[], referenceValueType=Net Value, unitType=SHARES, description=, name=Portfolio_REST_Test01}]
The problem arises when JSONAssert attempts to parse a named value where the value is an empty string, see "Description" in the examples above. JSONAssert is expecting a character to follow the equals-sign, not a comma, and throws an exception when encountered.
Digging further into this we found changes that must be made to HTTPBuilder to continue to get the unformatted responses 0.5.2 would provide.
Old Groovy code snip:
// perform a GET request, expecting JSON response data
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = restPath;
requestContentType = JSON;
uri.query = mapQuery;
headers.Accept = 'application/json';
// response handler for a successful response code:
response.success = { resp, json ->
// Check returned status'
assertResp(resp, expStatus);
return json.toString();
}
// Check returned status' for the 400's and 500's
response.failure = { resp ->
// Check returned status'
assertResp(resp, expStatus);
}
The HTTPBuilder documentation indicates automatic formatting will be used for known types like JSON and XML. In order to turn this feature off one must specify a ContentType of TEXT in the http.request. But when this is done the "json" object's toString value (within the response.success closure) no longer returns the returned JSON values. These values are found in the "text" property.
So the final code looks like this:
// perform a GET request, expecting JSON response data
http.request(Method.GET, ContentType.TEXT) { req ->
uri.path = restPath;
requestContentType = JSON;
uri.query = mapQuery;
headers.Accept = 'application/json';
// response handler for a successful response code:
response.success = { resp, json ->
// Check returned status'
assertResp(resp, expStatus);
return json.text;
}
// Check returned status' for the 400's and 500's
response.failure = { resp ->
// Check returned status'
assertResp(resp, expStatus);
}
Hopefully if someone encounters this same issue, they'll consult Stack Overflow and they'll find these notes helpful.
Best Regards

JSON, Servlet, JSP

Firstly, my HTTP POST through a URL accepts 4 parameters. (Param1, Param2, Param3, Param4).
Can I pass the parameters from the database?
Once the URL is entered, the information returned will be in text format using JSON
format.
The JSON will return either {"Status" : "Yes"} or {"Status" : "No"}
How shall I do this in servlets? doPost()
Just set the proper content type and encoding and write the JSON string to the response accordingly.
String json = "{\"status\": \"Yes\"}";
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);
Instead of composing the JSON yourself, you may consider using an existing JSON library to ease the job of JSON (de)serializing in Java. For example Google Gson.
Map<String, String> result = new HashMap<String, String>();
result.put("status", "Yes");
// ... (put more if necessary)
String json = new Gson().toJson(result);
// ... (just write to response as above)
Jackson is another option for JSON object marshalling.