Spring boot - Joda DateTime serialisation - java

In an Spring boot app, I have a DTO class with a org.joda.time.DateTime field type.
This DTO is the web response body in an endpoint and Spring boot is serialisating it to a timestamp.
I don't want that behaviors. Instead of that, I want DateTime to be serialised as a POJO.
This is an example:
Actual response:
{
"thisDate": 1566518936800
}
Expected response:
{
"thisDate": {
"monthOfYear": 8,
"centuryOfEra": 20,
"yearOfEra": 2019,
"yearOfCentury": 19,
"weekyear": 2019,
"weekOfWeekyear": 34,
"hourOfDay": 17,
"minuteOfHour": 8,
"secondOfMinute": 56,
"millisOfSecond": 800,
"secondOfDay": 61736,
"millisOfDay": 61736800,
"minuteOfDay": 1028,
"era": 1,
"dayOfMonth": 22,
"dayOfWeek": 4,
"dayOfYear": 234,
"year": 2019,
"chronology": {
"zone": {
"fixed": false,
"uncachedZone": {
"cachable": true,
"fixed": false,
"id": "America/Los_Angeles"
},
"id": "America/Los_Angeles"
}
},
"millis": 1566518936800,
"zone": {
"fixed": false,
"uncachedZone": {
"cachable": true,
"fixed": false,
"id": "America/Los_Angeles"
},
"id": "America/Los_Angeles"
},
"afterNow": false,
"beforeNow": true,
"equalNow": false
}
}
I know this is not the most common case but is what I need; actually the most common case is exactly the opposite.
Thanks in advance

Related

How to get a child object in response with java streams

Alrighty I've been banging my head in a wall whole day and cant solve this issue. I am trying to find an id in a object list which is like 3 levels down the hierarchy with java stream. I know how to do it with for loop but I need to get it with stream.
json response is
"NumberOfOwners": 1,
"CurrentPage": 1,
"TotalItems": 1,
"TotalPages": 1,
"PageSize": 1,
"PageItems": [
{
"Id": 1560,
"Title": "PlsWrk",
"IsSubmitted": true,
"Owner": {
"Branch": null,
"Position": null,
"Id": null,
"FirstName": null,
"LastName": null,
"ParentName": null,
"Gender": null,
"Image": null,
"LoginStatusId": 0,
"EmployeeStatus": 0,
"CompanyName": null,
"IsSubcontractor": false
},
"KeyResults": [
{
"Id": 5032,
"Title": "asdf1",
"OverallStatus": 2,
"MonthKeyResults": [
{
"Id": 12484,
"Month": 9,
"Status": 3,
"Progress": "REaplace1"
},
{
"Id": 12483,
"Month": 8,
"Status": 3,
"Progress": "sadf4"
},
{
"Id": 12482,
"Month": 7,
"Status": 1,
"Progress": "On Track1"
}
]
},
{
"Id": 5033,
"Title": "asdf2",
"OverallStatus": 1,
"MonthKeyResults": [
{
"Id": 12485,
"Month": 7,
"Status": 2,
"Progress": "Recovery2"
},
{
"Id": 12487,
"Month": 9,
"Status": 2,
"Progress": "asdfreas"
},
{
"Id": 12486,
"Month": 8,
"Status": 1,
"Progress": "asdf5"
}
]
},
{
"Id": 5034,
"Title": "asdf3",
"OverallStatus": 2,
"MonthKeyResults": [
{
"Id": 12490,
"Month": 9,
"Status": 1,
"Progress": "asdafa"
},
{
"Id": 12489,
"Month": 8,
"Status": 2,
"Progress": "asdf6"
},
{
"Id": 12488,
"Month": 7,
"Status": 3,
"Progress": "Replace3"
}
]
}
]
}
]
Precisely I want stream to return MonthyKeyResult object with a specific id
Atm I am here
public static MonthKeyResults getOkrMonthlyProgressById(PageItems okr, Integer monthlyProgressId){
//here i get KeyResults object list
List<KeyResults> keyResult = okr.getKeyResults().stream().collect(Collectors.toList());
//and now I am trying to get all MonthKeyResults
//objects but I not doing it right
List<MonthKeyResults> monthKeyResults = keyResult.stream().
filter(monthKeyResult -> monthKeyResult.
getMonthKeyResults().
stream().collect(Collectors.toList()));
//and then I am thinking of going trough the monthKeyResults
//list with stream and finding Id I need and returning that
//whole object with something like this
MonthKeyResults mKeyResults = monthKeyResults.stream().filter(id -> id.getId().
equals(monthlyProgressId)).findAny().orElse(null);
return mKeyResult
}
I got one more question
I've separated getting the final object as you see in 3 streams, is it possible to get it in one go or you need to separate this objects like this and go trough them separately?
Probably you're looking for something like:
return okr.getKeyResults().stream()
.flatMap(keyResult -> keyResult.getMonthKeyResults().stream())
.filter(monthKeyResult -> monthKeyResult.getId().equals(monthlyProgressId))
.findAny()
.orElse(null);
Edit: fixed typo.

Incorrect totalElements and totalPages values for Spring Page

I have 21 rows in a database and I am using Spring's Page to get them.
If I specify a page size less than 22, it will show totalElements: 3864 and totalPages is also wrong. What could be wrong?
Example:
GET myurl.com/foo?size=5
yields a result like this
{
"content": [
{
{ "pretend_that": "there are five elements here" }
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 5,
"paged": true,
"unpaged": false
},
"last": false,
"totalPages": 773,
"totalElements": 3864,
"size": 5,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"first": true,
"numberOfElements": 5,
"empty": false
}
Example 2:
GET myurl.com/foo?size=50
yields a result like this
{
"content": [
{
{ "pretend_that": "there are 21 elements here" }
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageNumber": 0,
"pageSize": 50,
"paged": true,
"unpaged": false
},
"last": true,
"totalPages": 1,
"totalElements": 21,
"size": 50,
"number": 0,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"first": true,
"numberOfElements": 21,
"empty": false
}
P.S. if I get the final page, it shows the page and elements count correctly.
I have tried changing Spring Boot versions and that hasn't helped.

Deserialize(convert) a JsonObject to DateTime without POJO

I have the following jsonObject:
"dateCreated": {
"year": 2021,
"dayOfYear": 145,
"equalNow": false,
"weekyear": 2021,
"chronology": {
"zone": {
"ID": "UTC"
}
},
"weekOfWeekyear": 21,
"secondOfMinute": 10,
"millisOfDay": 10990000,
"monthOfYear": 5,
"dayOfWeek": 2,
"beforeNow": true,
"minuteOfDay": 183,
"dayOfMonth": 25,
"era": 1,
"zone": {
"ID": "UTC"
},
"yearOfCentury": 21,
"centuryOfEra": 20,
"hourOfDay": 3,
"secondOfDay": 10990,
"millis": 1621911790000,
"yearOfEra": 2021,
"minuteOfHour": 3,
"millisOfSecond": 0,
"afterNow": false
}
I need to convert it for this format:
2021-05-25T03:03:10.000Z
Since I don't have a pojo for that object, it's coming from a jsonArray, I'm struggling to get a Datetime from it.
I tried ObjectMapper, JSON(GSON) and still no success.
Does anyone have a clue how can I do it?
edit.: It's a list of Recordings that I converted to JsonArray (to manipulate, adding another field into the json). When I convert the list to jsonArray, that field (type DateTime) becomes serialized and I need it back to the correct format to pass it forward.
Recording.class;
private final DateTime dateCreated;
List<Recording> listRecordings;
JSONArray jsonArray = new JSONArray(listRecordings);
jsonArray ->
[
{
"offset": 179161383840,
"type": "AUDIO",
"duration": 232,
"codec": "OPUS",
"dateCreated": {
"year": 2021,
"dayOfYear": 145,
"equalNow": false,
"weekyear": 2021,
"chronology": {
"zone": {
"ID": "UTC"
}
},
"weekOfWeekyear": 21,
"secondOfMinute": 10,
"millisOfDay": 10990000,
"monthOfYear": 5,
"dayOfWeek": 2,
"beforeNow": true,
"minuteOfDay": 183,
"dayOfMonth": 25,
"era": 1,
"zone": {
"ID": "UTC"
},
"yearOfCentury": 21,
"centuryOfEra": 20,
"hourOfDay": 3,
"secondOfDay": 10990,
"millis": 1621911790000,
"yearOfEra": 2021,
"minuteOfHour": 3,
"millisOfSecond": 0,
"afterNow": false
},
"size": 521517,
"containerFormat": "MKA",
"status": "COMPLETED"
}
]
I need to revert back dateCreated for the original format: 2021-05-25T03:03:10.000Z
Edit3.:
My workaround:
for (Recording recording : listRecordings) {
Object jsonObject = JSONObject.wrap(recording);
((JSONObject) jsonObject).put("dateCreated", recording.getDateCreated());
jsonArray.put(jsonObject);
}
Best Regards,

Is it possible to turn an array of objects into a map during deserialisation using Gson?

Using the Steam API found here api.steampowered.com/IEconItems_440/GetPlayerItems/v0001/ I get a JSON string like the one below. As you can see, it contains an array of item objects. What I'd like to do is to turn this array into a Map where the defindex is the key and the value is the corresponding item object at point of deserialisation using GSON.
Is this possible or do I have to do that after it's created the objects and populated the array?
"result": {
"status": 1,
"num_backpack_slots": 800,
"items": [
{
"id": 12222222,
"original_id": 333333333,
"defindex": 45,
"level": 10,
"quality": 3,
"inventory": 2147483922,
"quantity": 1,
"origin": 0,
"style": 0,
"attributes": [
{
//...
]
},
{
"id": 3332222222,
"original_id": 554545465,
"defindex": 116,
"level": 10,
"quality": 6,
"inventory": 2147483865,
"quantity": 1,
"origin": 0,
"equipped": [
{
"class": 6,
"slot": 7
},
{
"class": 8,
"slot": 7
}
]
,
"style": 1,
"attributes": [
//...
]
},
{
"id": 4658518468,
"original_id": 897545164648,
"defindex": 130,
"level": 5,
"quality": 3,
"inventory": 2147484134,
"quantity": 1,
"origin": 0,
"attributes": [
{
//...
]
}
]

GSON cannot parse Zomato restaurant collection

I am using Java and Akka to design new app at home, but I am facing problems pasing api response from Zomato.
The JSON response can be found below. I've created Class Restaurant with List of objects Restaurant. How should I parse it?
{
"results_found": 131,
"results_start": 0,
"results_shown": 10,
"restaurants": [
{
"restaurant": {
"R": {
"res_id": 6103211
},
"apikey": "4972ea7a10293fc07e997364eef03d3d",
"id": "6103211",
"name": "Dishoom",
"url": "https://www.zomato.com/london/dishoom-covent-garden?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"location": {
"address": "12 Upper St Martin's Lane, Covent Garden, London WC2H 9FB",
"locality": "Upper St Martin's Lane, Covent Garden",
"city": "London",
"city_id": 61,
"latitude": "51.5124170000",
"longitude": "-0.1271640000",
"zipcode": "WC2H 9FB",
"country_id": 215,
"locality_verbose": "Upper St Martin's Lane, Covent Garden, London"
},
"switch_to_order_menu": 0,
"cuisines": "Indian, North Indian, Curry, Cafe",
"average_cost_for_two": 35,
"price_range": 2,
"currency": "\u00a3",
"offers": [],
"thumb": "https://b.zmtcdn.com/data/res_imagery/6103211_RESTAURANT_19f7b41684765da1a700c2818f16cde0.jpg?fit=around%7C200%3A200&crop=200%3A200%3B%2A%2C%2A",
"user_rating": {
"aggregate_rating": "4.9",
"rating_text": "Excellent",
"rating_color": "3F7E00",
"votes": "919"
},
"photos_url": "https://www.zomato.com/london/dishoom-covent-garden/photos?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1#tabtop",
"menu_url": "https://www.zomato.com/london/dishoom-covent-garden/menu?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1&openSwipeBox=menu&showMinimal=1#tabtop",
"featured_image": "https://b.zmtcdn.com/data/res_imagery/6103211_RESTAURANT_19f7b41684765da1a700c2818f16cde0.jpg",
"has_online_delivery": 0,
"is_delivering_now": 0,
"include_bogo_offers": true,
"deeplink": "zomato://restaurant/6103211",
"has_table_booking": 0,
"events_url": "https://www.zomato.com/london/dishoom-covent-garden/events#tabtop?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"establishment_types": []
}
},
If the json is exactly the same of what you've pasted here, it seems that it's not a valid json. Try with this one:
{
"results_found": 131,
"results_start": 0,
"results_shown": 10,
"restaurants": [{
"restaurant": {
"R": {
"res_id": 6103211
},
"apikey": "4972ea7a10293fc07e997364eef03d3d",
"id": "6103211",
"name": "Dishoom",
"url": "https://www.zomato.com/london/dishoom-covent-garden?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"location": {
"address": "12 Upper St Martin's Lane, Covent Garden, London WC2H 9FB",
"locality": "Upper St Martin's Lane, Covent Garden",
"city": "London",
"city_id": 61,
"latitude": "51.5124170000",
"longitude": "-0.1271640000",
"zipcode": "WC2H 9FB",
"country_id": 215,
"locality_verbose": "Upper St Martin's Lane, Covent Garden, London"
},
"switch_to_order_menu": 0,
"cuisines": "Indian, North Indian, Curry, Cafe",
"average_cost_for_two": 35,
"price_range": 2,
"currency": "\u00a3",
"offers": [],
"thumb": "https://b.zmtcdn.com/data/res_imagery/6103211_RESTAURANT_19f7b41684765da1a700c2818f16cde0.jpg?fit=around%7C200%3A200&crop=200%3A200%3B%2A%2C%2A",
"user_rating": {
"aggregate_rating": "4.9",
"rating_text": "Excellent",
"rating_color": "3F7E00",
"votes": "919"
},
"photos_url": "https://www.zomato.com/london/dishoom-covent-garden/photos?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1#tabtop",
"menu_url": "https://www.zomato.com/london/dishoom-covent-garden/menu?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1&openSwipeBox=menu&showMinimal=1#tabtop",
"featured_image": "https://b.zmtcdn.com/data/res_imagery/6103211_RESTAURANT_19f7b41684765da1a700c2818f16cde0.jpg",
"has_online_delivery": 0,
"is_delivering_now": 0,
"include_bogo_offers": true,
"deeplink": "zomato://restaurant/6103211",
"has_table_booking": 0,
"events_url": "https://www.zomato.com/london/dishoom-covent-garden/events#tabtop?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"establishment_types": []
}
}]
}
The first thing is the JSON is invalid. I assume you can manage a valid JSON. After validating the JSON.
Create a Restaurant POJO class first.
The properties for Restaurant class:
R: obj
apikey: string
location: obj
.... like .....
add all the fields that you need.
After that, Use code to parse. but first, fetch out the restaurants array from the JSON.
gson.fromJson(restaurants, Restaurant[].class);

Categories

Resources