i make a post to an api with rest assured. and than i try to make sure expected data from responsed data ,
but i got some errors like this -> "java.lang.IllegalArgumentException: The parameter "data" was used but not defined. Define parameters using the JsonPath.params(...) function"
my code:
String payload_data = "{" +
"\"Time\":1638057600, " +
"\"exampleType\":example, " +
"\"Id\":[2]}";
RestAssured.defaultParser = Parser.JSON;
given().
contentType(ContentType.JSON).
body(payload_data).
when().
post(api_url).
then().
statusCode(200).
body("data.examples.2.exampleData", equalTo("33"));
}
my json data
{
"success": true,
"data": {
"examples": {
"2": {
"ex_data": 0,
"exampleData": 33,
"data_ex": 0,
}
}
}
First, I tested path "data.examples.2.exampleData" with your json, it works fine. No problem.
You made some mistakes here.
Your payload is invalid json.
{
"Time": 1638057600,
"exampleType": example, //it must be number or String with double quote
"Id": [
2
]
}
You are comparing 2 things with different data types.
"data.examples.2.exampleData" --> int 33
equalTo("33") --> String "33"
Fix: body("data.examples.2.exampleData", equalTo(33));
Related
I am new to RedisSearch. I have a Java client. What is the easiest way to parse this sample FT.SEARCH result into JSON or POJO or something more useful?
Sample result from FT.SEARCH (actually a string):
[
3,
movie_json: 1, [$, { "id": 1, "title": "Game of Thrones" } ],
movie_json: 3, [$, { "id": 3, "title": "Looking for Sugarman" } ],
movie_json: 2, [$, { "id": 2, "title": "Inception" } ]
]
Something like this would be useful:
{
"count": 3,
"docs": [
{ "id": 1, "title": "Game of Thrones" },
{ "id": 3, "title": "Looking for Sugarman" },
{ "id": 2, "title": "Inception" }
]
}
The most obvious is a RegEx matcher as below (I am no regex expert).
This is the code generated by the https://regex101.com/ site where I can get the right groups on their site as long as I use a global flag - but it seems that Java doesn't have a GLOBAL pattern / flag! Is that true?
The code the site generated is below and sure enough matcher.find() shows no match, presumably due to the absence of the global flag.
final String regex = "(?<=\\[\\$, ).*?(?= \\])";
final String string = respContent; // The rediSearch result string shown above
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("Full match: " + matcher.group(0));
for (int i = 1; i <= matcher.groupCount(); i++) {
System.out.println("Group " + i + ": " + matcher.group(i));
}
}
I could use the String.split() dance too.
However, is there an existing solution that is probably more robust for multiple FT.SEARCH results use-cases?
I imagined someone would have written a RedisSearch results parser by now but I cannot find one.
Thanks,
Murray
The high level Redis API for Quarkus only exposes the plain Redis commands as a set of java APIs. To handle Redis extensions, you can always refer to the low-level API: https://quarkus.io/guides/redis-reference
Once you choose the low-level API, you are, in fact, using the underlying driver that Quarkus uses. This is Vert.x Redis client.
In this mode, you can use any Redis extension and work with JSON directly, for example:
// set a JSON value
lowLevelClient
.send(cmd(Command.create("JSON.SET")).arg("foo").arg(".").arg("\"bar\""))
.compose(response -> {
// OK
// get a JSON value
return lowLevelClient.send(cmd(Command.create("JSON.GET")).arg("foo"));
})
.compose(response -> {
// verify that it is correct
should.assertEquals("\"bar\"", response.toString());
// do another call...
return lowLevelClient.send(cmd(Command.create("JSON.TYPE")).arg("foo").arg("."));
})
.compose(response -> {
should.assertEquals("string", response.toString());
return Future.succeededFuture();
})
.onFailure(should::fail)
.onSuccess(v -> {
test.complete();
});
While this mode is much more verbose, it gives you full control to the Redis extension you're using.
If the response can be mapped to JSON or is JSON already, you can get the content from its holder directly without need to parse the response, for example:
response.getKeys(); // returns the set of keys
response.get("key1"); // returns the JSON value for key "key1"
response.get(0); // returns the JSON value for array index 0
...
I'm still kind of new to REST and haven't been able to figure this one out.
I have a response like this one:
{
"StatusCode": 200,
"Result": {
"CustomerStuff": {
"Name": "John",
"State": "Oregon",
"GetEmail": false
},
"eText": "Will only get paper mail. "
}
}
I would normally save the response body as a string and then use a JsonPath to get what I need.
String responseBody = given().body().when().etc...;
JsonPath jsonPath = new JsonPath(responseBody).setRoot("Result.CustomerStuff");
Then get what I need:
String name = jsonPath.get("name");
I can't figure out how to get the, "eText" value. It's not in the same segment of the response.
Any suggestions?
You should use
JsonPath jsonPath = new JsonPath(responseBody).setRoot("Result")
And then call jsonPath.get("eText") in order to get the value you want.
You can still access CustomerStuff with jsonPath.get("CustomerStuff")
I am using JsonPath to retrieve a value from a JSON file. The JSON file looks something like this:
[
{
"username": "John",
"password": {
"passwordValue": "passwordjohn",
"secret_key": "123"
}
},
{
"username": "Nick",
"password": {
"passwordValue": "XXX",
"secret_key": "ZZZ",
"other_key": "YYY"
}
}
]
The JsonPath I am using is to retrieve the password from a particular user. Example:
fun getPassword() {
val passwords: JSONArray = read(jsonFile, "\$.[?(#.name==\"John\")].password")
}
However, I found two obstacles. Firstly, I get back a net.minidev.json.JSONArray always, and the same path with appended [0] doesn't work.
Therefore, I try to get the only element from the JSONArray I get back, like this: credentials[0]. Unfortunately, this removes the double quotes in the field names, resulting in something like this:
{passwordValue: passwordjohn, secret_key: 123}
Which is impossible to work with.
I am looking for a way to get this back:
{"passwordValue": "passwordjohn", "secret_key": "123"}
What I ended up doing was to remove the [ and ] symbols from the beginning of the JSONArray after converting it to a String:
private fun JSONArray.toCredentialString(): String {
val credentialString = this.toString()
return credentialString.substring(1, credentialString.length - 1)
}
Any better solution is welcome.
I'm having trouble passing a complex json object in angularjs with $http.post. I'm keep getting a 400 bad request error sent back from the server saying the request was syntactically incorrect. I believe it has something to do with the array since it passes fine when i don't include it.
json i'm passing.
{
customer: {
firstName: "John",
lastName: "Doe",
street: "1234 South Dr",
city: "Detroit",
state: "MI",
zip: "12345",
phone: "123-321-1234",
email: "EMAIL#GMAIL.COM"
},
order: {
orderDate: "06-16-2015",
registerNum: "1",
transactionNum: "7820",
deliveryStatusID: 1,
notes: "Hold order until July",
items: [
{skuID: "1234568",
skuDescription: "Order item 1",
qty: "4",
itemStatusID: 1,
itemStatusDescription: "Backorder"
},
{skuID: "7387491",
skuDescription: "Order item 2",
qty: "1",
itemStatusID: 1,
itemStatusDescription: "Flagged"
}
]
}
}
angular service function
this.addOrder = function(new_order) {
return $http.post(base + "/add", new_order);
};
Spring MVC controller method
#RequestMapping(value="/add", method=RequestMethod.POST)
public void addOrder(#RequestBody CustomerOrder customerOrder) {
System.out.println("----CUSTOMER-INFO----");
System.out.println(customerOrder.getCustomer().getFirstName());
System.out.println(customerOrder.getCustomer().getLastName());
System.out.println("");
System.out.println("----ORDER-INFO----");
System.out.println(customerOrder.getOrder().getOrderID());
System.out.println(customerOrder.getOrder().getOrderDate());
}
The problem only seems to occur when I pass the items array in the json. I've passed the same json object without the items array and it works fine. The format of the json is being sent in the same format that gets returned whenever I GET an order with my angularjs service method so I'm really not sure as to where I'm going wrong with this.
If I need to provide more code please let me know. I appreciate any effort in helping me out.
Thank you.
Jason
Well after struggling to find my error in this problem, I finally found a solution. I thought I'd share how I debugged and fix this problem in case someone else is in a similar situation as I was.
After trying every possible way of sending my data in angular to the server and continually getting the same HTTP 400 error, I decided to send the json as a string and accept the json as a string in my spring mvc controller like this.
angular service method:
this.addOrder = function(new_order) {
return $http.post(base + "/add", angular.toJson(new_order));
};
spring controller
#RequestMapping(value="/add", method=RequestMethod.POST, consumes="application/json")
public void addOrder(#RequestBody String json) {
}
From here I simply took the json passed in and used the Jackson ObjectMapper to convert the json string to my POJO like this.
mapping json string to pojo
#RequestMapping(value="/add", method=RequestMethod.POST, consumes="application/json")
public void addOrder(#RequestBody String json) {
ObjectMapper mapper = new ObjectMapper();
try {
CustomerOrder order = mapper.readValue(json, CustomerOrder.class);
System.out.println(order.getCustomer().getFirstName() + " " + order.getCustomer().getLastName());
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
After doing this and running my code, I would get an UnrecognizedPropertyException on a field in my Items class when trying to bind the items json to the List in my Order class. It was just a simple mispelling on the json side and I completely missed it. After correcting this, jackson mapped everything correctly and I no longer get this HTTP 400 Error The request was syntactically incorrect.
Another thing to note is that if you pass your object as a string in angular using the JSON.stringify you may encounter this same exception on hashKey field in the JSON object. The hashKeys are used by angular to monitor changes. I believe you can use a jackson annotation to ignore unknown fields or you can simply use angular.toJson instead which will remove all the hasKey/values for you which is what I did.
Just formatted the Json in a better way. Try this if it helps. Also, post the java classes if possible:
{
"customer": {
"firstName": "John",
"lastName": "Doe",
"street": "1234 South Dr",
"city": "Detroit",
"state": "MI",
"zip": "12345",
"phone": "123-321-1234",
"email": "EMAIL#GMAIL.COM"
},
"order": {
"orderDate": "06-16-2015",
"registerNum": "1",
"transactionNum": "7820",
"deliveryStatusID": 1,
"notes": "Hold order until July",
"items": [
{
"skuID": "1234568",
"skuDescription": "Order item 1",
"qty": "4",
"itemStatusID": 1,
"itemStatusDescription": "Backorder"
},
{
"skuID": "7387491",
"skuDescription": "Order item 2",
"qty": "1",
"itemStatusID": 1,
"itemStatusDescription": "Flagged"
}
]
}
}
I have a URL request like this:
http://localhost:8080:_dc=1367504213107&filter[0][field]=site&filter[0][data][type]=string&filter[0][data][value]=test&filter[1][field]=address&filter[1][data][type]=string&filter[1][data][value]=Columbus
This is the URL request that I get from browser.
From this URL, I need to get the filter related data as a JSON object.
Basically I have filter parameters like these in the requested URL:
filter[0][field]=site
filter[0][data][type]=string
filter[0][data][value]=test
filter[1][field]=address
filter[1][data][type]=string
filter[1][data][value]=Columbus
I am using the Spring MVC framework.
Those URL parameters aren't in JSON format. I'm not sure what your question / problem is here... can't you just read in each of those parameters from the URL and then parse the data out of the strings as you need? You could take it as a single parameter and tokenize based on a custom character, or you could just loop through all the parameters and parse each one and add them to an array.
Are you saying that you need to return the data in JSON format? Get your data using the parsed parameters as I described above, then when you have the data merely serialize that object and pass it back over the wire as the body of the response. You'll want to use a JSON serialization library like Jackson which will write the object to a string in JSON for you.
This is what that data would probably look like if it were written in JSON:
{
"filter":
[
{
"field": "site",
"data":
{
"type": "string",
"value": "test"
}
},
{
"field": "address",
"data":
{
"type": "string",
"value": "Columbus"
}
}
]
}
Java code that translates from the above JSON to your-format:
JSONObject root = new JSONObject(json);
JSONArray filters = root.getJSONArray("filter");
for (int i = 0; i < filters.length(); i++)
{
JSONObject filter = filters.getJSONObject(i);
String field = filter.getString("field");
JSONObject data = filter.getJSONObject("data");
String dataType = data.getString("type");
String dataValue = data.getString("value");
System.out.println("filter[" + i + "][field]=" + field);
System.out.println("filter[" + i + "][data][type]=" + dataType);
System.out.println("filter[" + i + "][data][value]=" + dataValue);
}
Your data format does not appear to be standard, so you will have to parse it yourself.