Matching object in JSON with jsonpath in Spring Boot Test - jsonpath

I'm trying to write unit tests for a rest endpoint with Spring Boot Test that's going well but when I try to assert on an object in the json response with jsonPath an AssertionError is thrown even when contents are identical and the same.
Sample Json
{
"status": 200,
"data": [
{
"id": 1,
"placed_by": 1,
"weight": 0.1,
"weight_metric": "KG",
"sent_on": null,
"delivered_on": null,
"status": "PLACED",
"from": "1 string, string, string, string",
"to": "1 string, string, string, string",
"current_location": "1 string, string, string, string"
}
]
}
Code in Kotlin
mockMvc.perform(
get("/api/v1/stuff")
.contentType(MediaType.APPLICATION_JSON_UTF8)
).andExpect(status().isOk)
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("\$.status").value(HttpStatus.OK.value()))
.andExpect(jsonPath("\$.data.[0]").value(equalTo(stuffDTO.asJsonString())))
That throws AssertionError but the values are the same
Clicking on see difference says
How can I match an object in JSON with jsonPath? I need to be able to match an object because the object can contain many fields and it will be a PITA to match them individually

I came across what looks like the same issue, though it's hard to say without knowing what your asJsonString function is. Also I was using Java, not Kotlin. If it is the same issue:
It's due to jsonPath(expression) not returning a string, so matching it with one doesn't work. You need to convert stuffDTO into the correct type for matching using JsonPath ie. in a function such as:
private <T> T asParsedJson(Object obj) throws JsonProcessingException {
String json = new ObjectMapper().writeValueAsString(obj);
return JsonPath.read(json, "$");
}
Then .andExpect(jsonPath("\$.data.[0]").value(equalTo(asParsedJson(stuffDTO)))) should work.

Related

Using Retool to Update Dynamodb Item - ExpressionAttributeValues contains invalid key: Syntax error; key: "44" id

I'm using the Dynamodb resource in Retool, which is successful for GETs/Scans/Puts/Queries, but I can't seem to get an UpdateItem statement to work.
I'm trying to update an item to add a key for a list of maps if it doesn't exist and append an item if the key already does exist.
Configuration
Update Expression
SET images = list_append(:val, if_not_exists(images, :emptylist))
ExpressionAttributeValues
In Retool, my ExpressionAttributeValues are
":val": [{"location": "{{s3Uploader1.s3FolderName}}/{{s3Uploader1.s3FileName}}"}], ":emptylist":[], which pulls the s3 folder and file names from an s3Uploader and renders to ":val": [{"location": "redactedpath/redacted/redactedfilename"}], ":emptylist":[]
I originally tried the format of calling out the data types, e.g. "M", "L", etc, but I got exactly the same error.
":val":
{
"L":
[
{
"M":
{
"location":
{
"S": "{{s3Uploader1.s3FolderName}}/{{s3Uploader1.s3FileName}}"
}
}
}
]
},
":emptylist":
{
"L":[]
}
Result/Error
When I run the query, I get the following error:
statusCode:422
error:"Unprocessable Entity"
message:"ExpressionAttributeValues contains invalid key: Syntax error; key: "44""
data:null
estimatedResponseSizeBytes:147
resourceTimeTakenMs:363
isPreview:false
resourceType:"dynamodb"
lastReceivedFromResourceAt:1644774304601
source:"resource"
From my understanding, that error message usually specifies the actual key that caused the problem, but from what I can tell, my ExpressionAttributeValues does not contain the string 44. I'm wondering if this is something coming from Retool or if it's perhaps a location instead of the actual key.
I've dug through what feels like the depths of StackOverflow to try different things, but now I feel like I'm stuck.
Additional Information
My original ExpressionAttributeValues was based on Is it possible to combine if_not_exists and list_append in update_item
Similar question, but no answer and different key: ValidationException: ExpressionAttributeValues contains invalid key
Is there anything in the ExpressionAttributeValues that looks like it could cause that error?

How to select an element which has () in it using JSON

I am using RestAssured for API automation and as a part of it I have to extract a value from the JSON reponse.
JSON reponse is given below
{
"resourceName": "SERVICE_STATUS",
"records": [
{
"CREATED_DTTM": "2019-08-12T05:58:12.940Z",
"STATUS": "SUCCESS",
"SERVICE_EXECUTION_ID": "e760bed8-2ebb-4563-9812-7c0e5ed565cf",
"OUTPUT_FILE(S)": [
"FileC_FileA.csv"
],
"SERVICE_ID": "EXCEL2CSV"
}
],
"status": "SUCCESS"
}
I have to extract the value "FileC_FileA.csv" from the response, but when i do it via Json Path it is failing as "()" has special meaning in json path.
JsonPath js1 = new JsonPath(statusrespstring);
String outputfile = js1.get("OUTPUT_FILE(S)"); -----> This is failing
I have tried using
String outputfile = js1.get("OUTPUT_FILE"+"("+"S"+")");
String outputfile = js1.get('OUTPUT_FILE(S)');
But getting error as
: The parameter "S" was used but not defined. Define parameters using the JsonPath.params(...) function
Someone please help, how to select a value whose key parameter has () in it.
I have found the solution.
ArrayList<String> outputfile = js1.get("records[0].'OUTPUT_FILE(S)'");
If the property has special character then surrounding with single quotes will work.
Reference : https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html

Complex object in a query string

How can I have this structure in a query string?
"properties": {
"list": [
{
"label": "bye",
"value": "world"
},
{
"label": "hello",
"value": "mars"
}
]
}
I've tried it with properties[][list][label]=bye&properties[][list][value]=world&properties[0][label]=hello&properties[0][value]=mars and also with properties[][list][label]=bye&properties[][list][value]=world&properties[][list][label]=hello&properties[][list][value]=mars, none of them worked. I built them in php with http_build_query.
I need to have this structure in a query string because I have to send the data along with some other stuff with POST to a PHP site.
I see two errors in your query string:
properties is an object, so there's no need to use [] to add elements.
list is an array, so you must use numeric indexes in the query string.
The correct query string is:
?properties[list][0][label]=bye
&properties[list][0][value]=world
&properties[list][1][label]=hello
&properties[list][1][value]=mars
(multi-lined for readability)

What is valid query string for null array item?

I have the object:
{
"items": [ null, 1, 2 ]
}
and two versions of query strings for it:
array=null&array=1&array=2
array=&array=1&array=2
Which of them is proper? Is there any commonly used convention for this case?
Upd: the problem with null is that ASP.NET interprets it as "null" string.
It depends entirely on what the recipient application expects and parses.
The thing is, though, receiving "null", "false" etc from the query string will of course be interpreted as a string value, and therefore falsy.
So in the URL some_script.php?foo=false
if (!empty($_GET['foo'])) //true - contaisn "false", a string, not a boolean
If you want to be sure the parameter is therefore evaluated to falsy, I would suggest passing it empty.

Fiddler HttpRequest Composer - json.stringify

I want to use Fiddler to compose a HTTPRequest to an ASP.Net MVC Controller/Action. However, in this request, I want to be able to pass a JSON object as an object, and not simply as key value pairs which map to the different arguments in the method. I want to be able to test passing a complex type as one argument in the Controller/Action method.
This can be done in JQuery using Json.stringify({{json here}}) which passes the object as an object to MVC, and doesn't parse it into KVPs. Once again, I'm just looking to be able to test the same behavior in Fiddler, if it's possible.
Fiddler Request
The answer to this was simpler than I thought. What Json.stringify does, at it's core, is to wrap the Json string into an object which then becomes one single solitary KVP object, which then gets auto mapped based on the members and values of the Json Object passed and cast into your complex type object argument in your controller/action.
So, all I had to do was wrap the JSON object notation,
{
"FirstName": "Your",
"LastName": "Mom",
"Email": "yourmom#gmail.com",
"FilmAndSiteUpdates": true,
"CompanyUpdates": true
}
into a Json object "instance" so to speak by assigning it to a member by the same name of the method signature, like so...
{
"input": {
"FirstName": "Your",
"LastName": "Mom",
"Email": "yourmom#gmail.com",
"FilmAndSiteUpdates": true,
"CompanyUpdates": true
}
}
...and ASP.NET MVC does the implicit casting for you.

Resources