I'm quite new to API testing, I am wondering how to best and simple load some body?
I created simple pojo classes, but i am having problems with nested json.
ex:
{
"listOfItems": [
{
"name": "name1",
"value": "Jack"
},
{
"name": "nameDate",
"value": "20-08-2021-08-00-00"
},
{
"name": "address",
"value": "address here",
}
{
"name": "name2",
"value": "Smith"
}
],
"something": [],
"size": 1
}
Then, in classes I used:
ClassName {
private List<ListOfItems> listOfItems;
private List<something> something;
private int size;
//setters and getters
}
and
Class ListOfItems{
private String name;
private String value;
//getters and setters
}
then in test class I am trying to use it, but have no idea how.
public Class Test {
ClassName className = new ClassName();
ListOfItems list = new ListOfItems();
//how to get list with 3x name and 3x value like in json?
className.setsize(150);
given().when().body(???).post("\endpoint").then()...
}
But I have no idea how to declare those 4 properties (name, value)
You are actually on a pretty good track, you can use Gson library to help you out, Here is the video example for your explanation which I used to learn Gson back when I needed it
Related
I have the following json file:
{
"authors":
[{"id":"author7",
"book":[
[
{
"value":{"pages":123}}]]},
{
"id": "author3",
"book": [
[
{
"value": {
"title": "LOTR"
}
},
{
"value": {
"boolean": false
}
},
],
[
{
"value": {
"pages": 350
}
},
{
"value": {
"boolean": false
}
},
],
[
{
"value": {
"boolean": false
}
},
{
"value": {
"pages": 150
}
},
]
]
},
}
I want to be able to create an object of Author but I am having problems while mapping the Json file with the Java classes I have created.
I understand that, while mapping the json file with the java classes, Authors class should have as fields
public class Authors{
private String authorId;
private Book book;
}
Class Book should be like this
public class Book {
private List<Values> values
public Book() {
}
}
But what about class Values?
public class Values{
private int pages;
private Boolean bool;
private String title;
public Values() {
}
}
Is this the correct way to map it? Because I see that if I create an object of Values it will ask me to modify the constructor or create a new constructor for each different object that comes from Json
Thank you for reading and helping!
Easy way out would to be to define Values by type 'object' as,
public class Book {
private List<Object> values
}
This way you won't run into the issue of having properties with null values when they don't exist in the JSON. Also, the JSON would be entirely parsed into an object even if new properties are get introduced (or which may not be defined under values class, as you have done above causing those not being mapped to the object).
However, when you are using 'object', be mindful with your logic that uses this parsed object. Although, you are assured to access the properties from the object as in the JSON, you will have to conditionally check whether the nessacary property exists first in each logical context to avoid possible undefined value errors.
I have a nested JSON that I want to loop through and get value based on key.
Data.json
{
"car": [
{
"date": 1324599600000,
"values": [
{
"name": "Audi",
"price": "11212.12"
},
{
"name": "Bmw",
"price": "22321.3"
},
{
"name": "Cittroen",
"price": "23432.2"
},
{
"name": "Tuareg",
"price": "556456.3"
}
]
}
I created 3 object models based on JSON data.
CarResponse.java
public class CarResponse {
#JsonProperty(value = "car")
List<Car> cars;
//getters,setters
Car.java
public class Car{
#JsonProperty("values")
private List<CarValue> carValue;
//getters, setters
CarValue.java
public class CarValue {
private String name;
private BigDecimal price;
//getters, setters
DataParse.java
public class DataParse{
CarResponse response;
public CarValue parse(){
CarValue carValue = new CarValue();
//NEED HELP WITH THIS PART
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
return quoteValue;
}
}
In JSON I need to check if car name is Audi and if car name is Tuareg then save it and display it.
Nested for loop part of code is not working
for(Car cars : response.getQuote()){
for(CarValue qv : cars.getCarValue()){
String type = qv.get("name").asText();
Decimal value = qv.get("price").decimalValue();
carValue.setName(qv.getName());
carValue.setPrice(qv.getPrice());
}
}
Just put it as an example of what I need to do in this step which is check for key in JSON and if it is that key with for example name = Audi then
carValue.setName(qv.getName());
With my code above I am getting this in the console.
carValue=[carValue{name=null, price=null}
Assuming that your deserialization is working correctly, you should change the part that "is not working" to:
String type = qv.getName();
BigDecimal value = qv.getPrice();
If for some reason you want to use this qv.get(key) method, you should post its implementation.
When getName and getPrice are still returning null, it means you have a problem with the deserialization, for example a wrong setter method name. Still, without the implementation is impossible to understand.
Here is the official documentation of Jackson, the library used by default with spring-boot for JSON serialization / deserialization.
And here is Spring blog post about it.
I am trying to find an optimal way to deserialize dynamic fields that all contain the same value object structure:
"data": {
"lastUpdate": 1605299294253,
"tableData": [
{
"recordId": 1,
"isSelected": 1,
"myKey1": {
"valueRef": 72,
"value": "Some value"
},
"myKey2": {
"valueRef": 0,
"value": "123"
}
}
]
}
For the tableData JSON array, I have tried this approach without success:
import lombok.Data;
import java.util.Map;
#Data
public class TableRowDataVO {
private Integer recordId;
private Integer recordStatus;
private Map<String, TableRowDetailVO> columnData1;
private Map<String, TableRowDetailVO> columnData2;
}
This class is nested into another class to encompass the entire JSON body in data:
public class TabularDataDTO {
private Long lastUpdate;
private List<TableRowDataVO> tableData;
}
and each dynamic field holds the same Object of the following type:
public class TableRowDetailVO {
private Integer valueRef;
private String value;
}
There is also no guarantee that there are only 2 dynamic keys. It can be 0 to many dynamic keys that are in TableRowDataVO, but if there are limitations that require me to settle with 2, I can do that, but if 0 to many dynamic fields are possible, that would be great. I am trying to use the ObjectMapper with TypeReference as TabularDataVO but it throws an exception. What is the proper way to design my objects such that TabularDataVO can be deserialized by the mapper?
since the key is dynamic so when you process data you need some special process.
#Data
public class NewDTO {
private Long lastUpdate;
private List<Map<String, Object>> tableData;
}
Just to understand your question correctly. You Json is like following: -
"data": {
"lastUpdate": 1605299294253,
"tableData": [
{
"recordId": 1,
"isSelected": 1,
"myKey1": {
"valueRef": 72,
"value": "Some value"
},
"myKey2": {
"valueRef": 0,
"value": "123"
}
}
]
}
Not like
"data": {
"lastUpdate": 1605299294253,
"tableData": [
{
"recordId": 1,
"isSelected": 1,
"keys": [
{
"valueRef": 72,
"value": "Some value"
},
{
"valueRef": 0,
"value": "123"
}
]
}
]
}
Latter can be easily deserialized using jackson library and defining keys as List<Map<String, Object>>
I am using jackson to map json which I get from my post rest api to map to a java object.
the json is represent by
{
"baseName": "xyz",
"salary": [
{
"id": 1,
"info": {
"ename": "john",
"eid": 143
}
},
{
"id": 2,
"info": {
"ename": "bg",
"eid": 123
}
}
]
}
The java class are represent by
BaseInfo.java
class BaseInfo {
String baseName;
ArrayList<salary> salaries = new ArrayList<salary>();
}
Salary.java
class Salary {
int id;
EmplInfo emp;
}
EmplInfo.java
class EmplInfo{
String ename;
int eid;
}
But in the when call the api with this json I get the arraylist initialized but contains nothings. What I am doing wrong ? I get other information like baseName,etc
You can use the JsonProperty annotation to rename properties
class BaseInfo {
String baseName;
#JsonProperty("salary")
ArrayList<salary> salaries = new ArrayList<salary>();
}
class Salary {
int id;
#JsonProperty("info")
EmplInfo emp;
}
Following are the solutions:
Either add JsonProperty annotations as specified by Michael or update json keys i.e 'salary' to 'salaries' and 'info' to 'emp'
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I'm working out a problem, and this part of it I could use some assistance on, I have the following JSON array:
parentArray: [{"name":"folder1","children":[],"parent":"root","type":"folder"}, {"name":"folder2","children":[],"parent":"folder1","type":"folder"}]
I need to create a method that will put the put the object with name 'folder2' in to the 'children' array of 'folder1'.
Thanks for any help or pointers.
You can achieve it in a cleaner way using gson.
Create a POJO for Parent and an array value of type Parent[]
public class Parent {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getParent() {
return parent;
}
public void setParent(String parent) {
this.parent = parent;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Parent[] getChildren() {
return children;
}
public void setChildren(Parent[] children) {
this.children = children;
}
private String name;
private String parent;
private String type;
private Parent[] children;
}
Easily read the json and manipulate the Parent object thus returned:
BufferedReader br = new BufferedReader(new FileReader("array.json")); //File containing your initial json
Gson gson = new Gson();
Parent[] parentObjArray = gson.fromJson(br, Parent[].class);
Parent folder2 = parentObjArray[1];
parentObjArray[0].setChildren(new Parent[] { folder2 });
System.out.println(gson.toJson(parentObjArray));
Resulting json:
[
{
"name": "folder1",
"parent": "root",
"type": "folder",
"children": [
{
"name": "folder2",
"parent": "folder1",
"type": "folder",
"children": []
}
]
},
{
"name": "folder2",
"parent": "folder1",
"type": "folder",
"children": []
}
]
The above code uses a few assumptions specifically the exact indexes of your json array. You can further generalize and manipulate the json in accordance to your requirements.
Further, the 2nd element of the array can be removed to hold a single object with a child.
EDIT:
As per your new requirement, you might want to add the files and folders too. Adopting my dirty approach I can manually set these values. However, would definitely stress on that Files and Folders can share a single data type - Parent, hence this solution becomes a good candidate to adopt a recursive approach.
So it's:
Folder1
||=> File1
||=> Folder2
||=> File2
Changed inout json:
[
{
"name": "folder1",
"children": [],
"parent": "root",
"type": "folder"
},
{
"name": "folder2",
"children": [],
"parent": "folder1",
"type": "folder"
},
{
"name": "file1",
"parent": "folder1",
"type": "file"
},
{
"name": "file2",
"parent": "folder2",
"type": "file"
}
]
Manually set these values and modify json
Gson gson = new Gson();
Parent[] parentObjArray = gson.fromJson(br, Parent[].class);
Parent file2 = parentObjArray[3];
parentObjArray[1].setChildren(new Parent[] { file2 });
Parent folder2 = parentObjArray[1];
Parent file1 = parentObjArray[2];
parentObjArray[0].setChildren(new Parent[] { file1, folder2 });
parentObjArray = new Parent[]{parentObjArray[0]};
System.out.println(gson.toJson(parentObjArray));
Modified json now:
[
{
"name": "folder1",
"parent": "root",
"type": "folder",
"children": [
{
"name": "file1",
"parent": "folder1",
"type": "file"
},
{
"name": "folder2",
"parent": "folder1",
"type": "folder",
"children": [
{
"name": "file2",
"parent": "folder2",
"type": "file"
}
]
}
]
}
]
Hope this gives you a better idea how your generic approach would be. Good luck!
I would suggest you go with plain objects and then convert them to json string.
public class Folder {
private String name;
private List<Folder> children;
private String parent;
private String type;
//Getter and setters
}
This way you can create folder from json and also write folder to json
ObjectMapper mapper = new ObjectMapper();
String temp = mapper.writeValueAsString(folderObject);