I have sent a request to a REST servlet and it returns a JSON array
- I need to get the JSON as a String for further processing.
Originally I used this to get the body:
DataNode result = body.get("carList");` return result.toString();`
Then tried to parse the body, which is originally JSON, but ...
This string threw an exception from the
Jackson
library:"Unexpected character ('c' (code 99)): was expecting double-quote to start field name at [Source: (String)"[{carNumber: 22248002, trailerNumber: }]"; line: 1, column: 4]"
- These are the expected values.
- They are not in a recognised JSON form.
For the example above the requirement is:
[ {"carNumber" : "1234", "trailerNumber" : "567"}, ... ]
- See: JSON.org
I have not (yet) found an example or guide rooting about in the documentation.
- I looked for things like
getJson()
,getRaw()
and such. I'm convinved it must be there. - In this case I want the entries from the list to use for testing an update operation.
- I looked for things like
Looking forward to your response.
CodePudding user response:
author of WebTau here, thank you for using it.
To get the DataNode
underlying value, return the node from the validation block. If the node represented object, than an instance of Map
will be returned. List
for JSON array and correspondent type like String
, Boolean
for simple values
Map<String, ?> bodyAsMap = http.get("/end-point", ((header, body) -> {
return body;
}));
Note that it is not JSON yet. At this point you can convert Map back to JSON using any standard libraries. Or use WebTau JsonUtils.serialize
.
Also worth noting that it is not the original response from the server, but rather parsed to DataNode, then to Map and then to String.
If you need to validate that JSON confirms to a schema you can use it directly inside the validation block
If you need original raw content, you can use undocumented http
method
public HttpResponse getToFullUrl(String fullUrl, HttpHeader requestHeader)
object it returns has getTextContent()
method to access originally received content.
Could you please elaborate why do you need raw content access? If there is a useful pattern, it may be a good idea to enable it in WebTau natively.
CodePudding user response:
As things go I got a bit lucky and found at least one working answer. The first thing to discover is that within a lambda body you can only assign a value to a what the compiler calls: "effectively final".
In this case I chose a StringBuilder
, could be a List<String>
I guess, some kind of container.
Here is a solution, though I haven't found a better way in the documentation as yet.
StringBuilder jsonString = new StringBuilder(100);
:
WebTauDsl.http.get( callUrl, restCallHeader, ((header, body) ->
{
try
{
DataNode result = body.get("carList");
JsonNode jsonNode = JsonUtils.convertToTree( result );
jsonString.append( jsonNode.toString() ); // jsonString is "effectively final"
}
// This is a @Test, bubble-up any Exception
}));
return jsonString.toString(); // Return value to @Test caller
What's happening?
jasonString
is REST list call's output/return value.WebTau
has some handy xpath like calls to get/check body content."carList"
is the JSON array ofcarNumber
values retrieved.- Use the helper class
JaonUtil
to conver the content from theget("carList")
to a JsonNode.- The JsonNode, must be declared inside the lambda closure.
jsonNode.toString()
returns a nicely formed JSON syntax for the array.- You probably need to do further parsing for more structured objects from a
jasonNode
. - This example is maybe a good start. Do what I did, see what you can glean from within the debugger ;-)
- You probably need to do further parsing for more structured objects from a
- Append the JSON string value to the
jasonString
StringBuilder.- Declaring the StringBuilder outside the lambda satisfies the "effectively final" constraint.
- At first I was a little concerned by that error.
- Finally return the JSON string to the @Test method that invoked this activity.
- I did it this way because there are several integration test cases that need to use that carList as a starting point to simulate client workflow.
- You might just want to use the string inline.
In this example I've got well formed JSON from the WebTau
HTTP
call from our REST servlet. It all makes much more sense to me now, the DataNode is a rich meta-data structure put together to help the common place test actions like checking if a list is returned (isList()) and check field values, etc.
It is good to know that when you need to do more, especially in integration testing situations the underlying REST structures are there ready and willing to be put to use.
This is my naive solution, that seems to work. I'm leaving the "tick" alone for a little time to get a better or more correct or "by design" solution which will be more helpful to those who come after. Happy testing.