Is there any way to manipulate json response in spring boot? - json

My project is about a shopping application build with Spring boot. When I get the shopping cart from the endpoint. It will return JSON like this
{
"shoppingCartCode": 2,
"productDetailList": [
{
"productDetailCode": 5,
"price": 21000.0,
"dateManufacture": "2021-09-23",
"quantity": 10,
"colorName": "Pink",
"warranty": 2,
"product": {
"prodCode": 2,
"prodName": "Z Flod 10",
"description": "Z Flod 10 Flippable then Break up",
"brand": {
"brandName": "Samsung",
"imageList": []
},
"shop": {
"shopCode": 5,
"shopName": "Montri Phone",
"shopDescription": "Strict security",
"type": "SELLER",
"imageList": []
}
},
"imageList": [
{
"imageName": "i-agree.png"
},
{
"imageName": "i-agree1.png"
},
{
"imageName": "i-agree2.png"
},
{
"imageName": "i-agree3.png"
}
]
}
]
}
I want to manipulate the imageList to like this
"imageList": ["i-agree.png","i-agree1.png","i-agree2.png","i-agree3.png"]
Is there any way to manipulate JSON before response?
or it might need POJO to wrap it up before response again?

You can achieve this with a custom serializer as follows:
public class ImageListConverter extends StdConverter<List<Image>, List<String>> {
#Override
public List<String> convert(List<Image> images) {
return images.stream().map(User::getImageName).collect(Collectors.toList());
}
}
Now you just need to annotate the imageList property:
public class ProductDetail {
#JsonSerialize(converter = ImageListConverter.class)
List<Image> imageList;
}
The other option would be changing List<Image> to List<String> and do the conversion when creating ProductDetail. It really depends on how you use ProductDetail elsewhere.

Related

Converting JSON to POJO class

I have been struggling with converting the below json .
Is the data class should be mapped as Map<String,Object>.Then use Object mapper class to all values?What is the best way to map below pojo
Json Response
{
"data": {
"Order": [
{
{
"Property1" : Number1
"Propery2": Number 2
},
"Lines": [
{
"Id": "123456",
"itemDescription": "Green glass",
}
],
"date": "",
"updateDate": ""
}
]
}
}
Data class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Details {
public Map<String,Object> data;
}

Display certain items from array of objects in recyclerview

From the code below, I want to display request_id, request_title, status, no of trucks in recyclerview using retrofit 2.0. How to do this?
Here is my nested array of objects.
[
{
"id": 96,
"request_id": 24365,
"request_title": "tsfghjjlfdsg;lhj",
"transport_co_id": 1,
"status": 1,
"truck_info": [
{
"driver_mobile": 2147483647,
"driver_name": "dsdsd",
"truck_no": 1111
},
{
"driver_mobile": 2147483647,
"driver_name": "add",
"truck_no": 727
}
]
},
{
"id": 97,
"request_id": "test123",
"request_title": "test title",
"transport_co_id": 1,
"status": 1,
"truck_info": [
{
"driver_mobile": 2147483647,
"driver_name": "dsdsd",
"truck_no": 1111
},
{
"driver_mobile": 2147483647,
"driver_name": "add",
"truck_no": 1
}
]
}
]
create retrofit interface , class
public class ChampApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

How to pass a JSON file from the back-end to the front-end

I have a JSON file with a list of products in my back-end ( Spring ). I want to be able to pass the content to the front-end ( in Angular ).
I have a JSON file in an assets folder in my front-end made with angular.
This is the JSON file:
[ {
"brand": "",
"category": {
"id": 29,
"name": "hand held"
},
"description": "New D131 Scanner complete",
"hidden": false,
"id": 10,
"image": null,
"productNumber": "E14NO1617",
"quantity":1
},
{
"brand": "",
"category": {
"id": 29,
"name": "hand held"
},
"description": "New D132 Scanner complete",
"hidden": false,
"id": 10,
"image": null,
"productNumber": "E14NO1617",
"quantity":1
},
{
"brand": "",
"category": {
"id": 50,
"name": "card reader"
},
"description": "USB,
"hidden": false,
"id": 26,
"image": null,
"productNumber": "ST-1044UB",
"quantity": 1
}
]
I then display the objects ( products in my case ) on a table with the following function in the service:
getTemplates() : Promise<Product[]> {
return this.http.get<Product[]>("http://localhost:4200/assets/BirdyProducts.json")
.toPromise();
}
This works exactly like I want it to be displayed,
But I don't want to store the the JSON in my front-end assets folder.
I want it to be in my back-end in a resources folder and send the file with a rest-controller and still get the same result.
I tried a lot with Objectmapper, JSONObjects,... but did not find a solution.
#Controller
public class BirdyProductsController {
#RequestMapping(
value = "/birdyProducts",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE
)
String getBirdyProducts() {
return "json/BirdyProducts.json";
}
}
This worked for me.
Path to JSON file: \src\main\resources\static\json\BirdyProducts.json
#RestController
#RequestMapping
public class ExampleController {
#GetMapping("/BirdyProducts")
public InputStreamResource getJsonFile() throws IOException {
return new InputStreamResource(new ClassPathResource("/assets/BirdyProducts.json").getInputStream());
}
}
When I request for http://localhost:8080/BirdyProducts I get the content of the file.
The file is in the \src\main\resources\assets folder on the backend side.

Extract records from huge Json File

I have a huge json file with 5500 records. The file display three levels as you see in the code and i want to extract all the records with a define level . How can i do that?
{
"Dictionary": {
"Words": [
{
"name": "fdfafd",
"level": "easy"
},
{
"name": "dfdaf",
"level": "medium"
},
{
"name": "ddsss",
"level": "difficult"
},
{
"name": "fdfafd",
"level": "easy"
},
{
"name": "dfdfadaf",
"level": "medium"
},
{
"name": "ddddsss",
"level": "difficult"
}
]
}
}
Its case of deep serialization. You need right object structure to accommodate it.
Such as following (add getters and setters and default constructor in case you overload constructor):
Class Dictionary{
List<Words> words;
Class Words {
String name;
String level;
}
}
While initialize serializer use something like :
jsonSerializer.include("words");
jsonSerializer.include("words.*");

Jackson JSON Not Formatting Correctly

I have data that looks like this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"data": {
"lib": {
"files": [
"data1",
"data2",
"data3",
"data4"
],
"another file": [
"file.jar",
"lib.jar"
],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
Here is the function I'm using to prettify the JSON data:
public static String stringify(Object o, int space) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I am using the Jackson JSON Processor to format JSON data into a String.
For some reason the JSON format is not in the format that I need. When passing the data to that function, the format I'm getting is this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"another data": {
"lib": {
"files": [ "data1", "data2", "data3", "data4" ],
"another file": [ "file.jar", "lib.jar" ],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
As you can see under the "another data" object, the arrays are displayed as one whole line instead of a new line for each item in the array. I'm not sure how to modify my stringify function for it to format the JSON data correctly.
You should check how DefaultPrettyPrinter looks like. Really interesting in this class is the _arrayIndenter property. The default value for this property is FixedSpaceIndenter class. You should change it with Lf2SpacesIndenter class.
Your method should looks like this:
public static String stringify(Object o) {
try {
ObjectMapper mapper = new ObjectMapper();
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(new Lf2SpacesIndenter());
return mapper.writer(printer).writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I don't have enough reputation to add the comment, but referring to the above answer Lf2SpacesIndenter is removed from the newer Jackson's API (2.7 and up), so instead use:
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
Source of the solution