JSON parser not returning numbers - java

I have the following JSON structure:
{
"status": "Completed",
"notes": null,
"members": {
"0": {
"year": "2",
"details": {
"id": "14899975",
"anotherId": "11013306"
},
"aName": "Fred",
"amounts": {
"First": 589.48,
"Second": 1000,
"Third": 339.48
}
},
"1": {
"year": "2",
"details": {
"id": "14899976",
"anotherId": "11013306"
},
"aName": "George",
"amounts": {
"First": 222.22,
"Second": 2000,
"Third": 22.22
}
},
"2": {
"year": 1,
"details": {
"id": "14899976",
"anotherId": "11013306"
},
"aName": "Albert",
"amounts": {
"First": 333.33,
"Second": 3000,
"Third": 33.33
},
}
}
}
I am using Spring RESTTemplate and JacksonMapping2HttpMessageConverter, and the following structures to receive the result of parsing the above JSON structure:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
private String status;
private String notes;
private Map<String,Struct1> quotes;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct1 {
private int year;
private Struct2 details;
private String aName;
private Struct3 amounts;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct2 {
private String id;
private String anotherId;
}
#JsonIgnoreProperties(ignoreUnknown = true)
class Struct3 {
private float First;
private float Second;
private float Third;
}
All of these also have appropriate setters and getters for all fields.
My problem is that the number values in Struct3 are not filled in. I've tried making them float, Float, String, and BigDecimal, and the result is either null or 0.0.
I've tried putting a breakpoint in the setter for the first field, hoping
What am I missing? Can the capital letters in the JSON be causing a problem, do I need alternate field names?

It turned out to be the capital letters at the beginning of the field names; I added annotations like #JsonProperty("First") on the line before the getter of the field, and renamed the field to first, and now it's working.

Related

Rest-assured why can't I send a post request from multiple POJO classes

i have JSON :
{
"id": "string",
"name": "string",
"port": 0,
"location": "string",
"useCustomLocation": true,
"inMemoryMode": true,
"enabled": true,
"active": true,
"autoStartup": true,
"partitions": [
{
"id": "string",
"name": "string",
"factorUser": {
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
},
"users": [
{
"username": "string",
"password": "string",
"admin": true,
"perms": "string"
}
]
}
]
}
My pojo classes:
public class Root {
private String id;
private String name;
private long port;
private String location;
private boolean useCustomLocation;
private boolean inMemoryMode;
private boolean enabled;
private boolean active;
private boolean autoStartup;
private Partition[] partitions;
//Getter and Setters simple variebles
public Partition[] getPartitions() {
return partitions;
}
public void setPartitions(Partition[] value) {
this.partitions = value;
}
}
Partition class:
public class Partition {
private String id;
private String name;
private User factorUser;
private User[] users;
//Getter and Setters simple variebles
public User getFactorUser() {
return factorUser;
}
public void setFactorUser(User value) {
this.factorUser = value;
}
public User[] getUsers() {
return users;
}
public void setUsers(User[] value) {
this.users = value;
}
}
and the next two classes work similarly(FactorUser and User)
my Test:
public void postBaseData() {
Root root = new Root();
Response response = given()
.contentType(ContentType.JSON)
.log().all()
.auth()
.preemptive()
.basic("login", "password")
.body(root)
.baseUri(BaseUrl + STORE_INSTANCE)
.when()
.post()
.then()
.extract().response();
System.out.println(response.getBody().asString());
Assert.assertEquals(200, response.statusCode());
}
Why is only part of the request sent to me? And therefore returning status code 400
Part of body which posted:
{
"id": null,
"name": null,
"port": 0,
"location": null,
"useCustomLocation": false,
"inMemoryMode": false,
"enabled": false,
"active": false,
"autoStartup": false,
"partitions": null
}
I understand that the error is somewhere in the initialization of nested classes, for example "partition", but I can not understand how to do it correctly.I asked a similar question with get, but for a long time I can’t figure out how to work with such complex json requests. I also tried the line: "private Partition[] partitions" changing to "private List<Partition> partitions" and etc... but I still can't send full json.
i don't use constructor because in POSTMAN i get 200 ok with empty fields
scr

how can i access nested array from mongoDB collection using spring boot?

I am writing a credit card management system. This is the DB for the project (each user can have many cards and each card can have many transactions)
DB code sample:
{
"_id": 1,
"name": "Jawad",
"lastname": "Zakhour",
"username": "jwdzkh",
"password": "pass123",
"cards": [{
"cardnumber": "1234-5678-9123-4567",
"cardholdername": "yolla kazan",
"expirationdate": "05/09/2021",
"cvv": "256",
"type": "Credit",
"creditlimit": "3500",
"transactions": [{
"date": "03/06/2020",
"amount": 750,
"receiptNo": "EAC-15-123-45678"
}, {
"date": "06/08/2020",
"amount": 320,
"receiptNo": "THY-18-568-5866"
}]
}, {
"cardnumber": "4589-3256-7841-9655",
"cardholdername": "nabil dagher",
"expirationdate": "06/07/2022",
"cvv": "365",
"type": "Debit",
"balance": "5200",
"transactions": [{
"date": "09/11/2019",
"amount": 90,
"receiptNo": "TYH-35-163-5896"
}, {
"date": "10/10/2020",
"amount": 120,
"receiptNo": "NJU-85-586-4287"
}]
}, {
"cardnumber": "8976-3154-3187-3659",
"cardholdername": "jawad zakhour",
"expirationdate": "06/07/2022",
"cvv": "365",
"type": "Debit",
"balance": "12000",
"transactions": [{
"date": "01/02/2018",
"amount": 14,
"receiptNo": "DFG-58-348-9863"
}, {
"date": "04/12/2019",
"amount": 550,
"receiptNo": "FGH-46-008-3478"
}]
}]
}
on java spring boot I have three models User, Card, Transaction.
#Data
#AllArgsConstructor
#Document(collection = "Vault")
public class Card {
private String cardnumber;
private String cardholdername;
private String expirationdate;
private String cvv;
private String type;
private String creditlimit;
private String balance;
private List<Transaction> transactions;
}
#Data
#AllArgsConstructor
#Document(collection = "Vault")
public class User {
#Id
private int id;
private String name;
private String lastname;
private String username;
private String password;
private List<Card> cards;
}
#Data
#AllArgsConstructor
public class Transaction {
private String date;
private int amount;
private String receiptNo;
}
and also I have created 2 repositories CardsRepository and UserRepository
How can I Return all cards of a specific user?
now i want to get all the transactions for a specific card how is that possible?
since every card has a list it should be possible..
To get transactions of a specific card, just use filter(<some_predicate>). For example,
val user = userRepository.findById(id).orElseThrow(() -> UserNotFoundException(id));
val transactions = user.getCards()
.stream()
.filter(card -> card.getCardNumber().equals("1111.."))
.findFirst()
.map(Card::getTransactions)
.orElseGet(Collections::emptyList);
Here, if a specific card that matches the predicate that cardNumber equals some input, it will be passed on to the next operation in the stream pipeline and findFirst() returns the first occurrence of such card.
Edit with request:
#GetMapping("/users/{username}/cards/{cardnumber}/transactions")
public List<Transaction> getTransactionByCardnumber(#PathVariable String username, #PathVariable String cardnumber) {
val user = userRepository.findById(id).orElseThrow(() -> UserNotFoundException(id));
val transactions = user.getCards()
.stream()
.filter(card -> card.getCardnumber().equals(cardnumber))
.findFirst()
.map(Card::getTransactions)
.orElseGet(Collections::emptyList);
}

Best Way to do Object Mapping with Nested Json

Currently I'm trying to write a site that interacts with a public API using Feign and Spring.
I'm having trouble deciding how to handle the object mapping for deeply nested JSON.
Ex:
[
{
"type": "console",
"category": "Console",
"result_count": 1,
"shown_count": 1,
"result": [
{
"name": "Nintendo Switch",
"id": "nintendo-switch",
"platform": {
"name": "Nintendo",
"category": "nintendo",
"type": "platform"
},
"image": {
"url": "https://encrypted-tbn1.gstatic.com/shopping?q=tbn:ANd9GcRqJYIheMDjTE9WAHjMSW4bjh7OplS7Bep9CdsBBLWMwGdXim7xOG4&usqp=CAc",
"height": 409,
"width": 631
},
"min_price": 205,
"variations": [
{
"items": [
{
"hex_code": "#696969",
"name": "Gray",
"id": "space-gray",
"type": "color"
},
{
"hex_code": "#C0C0C0",
"name": "Silver",
"id": "silver",
"type": "color"
}
],
"name": "Color",
"type": "color"
},
{
"items": [
{
"name": "Nintendo",
"id": "nintendo",
"type": "platform"
}
],
"name": "Platform",
"type": "platform"
}
]
}
]
}
]
As of now, I have a single Java file with a class for each object in the JSON, and I've considered having the Object mapper just put everything into a HashMap. Is there a more elegant way to do this?
public class SearchResults {
private List<SearchResult> products;
private int resultCount;
private String type;
}
class SearchResult {
private String name;
private String slug;
private Image image;
}
class Image {
private String URL;
private String height;
private String width;
}
Based on the json file provided i have designed the classes and also provided the code to parse the json file to java
public class Console{
String type;
String category;
int result_count;
int show_count;
Result [] result;
}
public class Result{
String name;
String id;
Platform platform;
Image image;
int mini_price;
Variation [] variations;
}
public class Platform{
String name;
String category;
String type;
}
public class Image{
String url;
int height;
int width;
}
public class Variation{
String name;
String type;
Item [] items;
}
public class Item{
String hex_code;
String name;
String id;
String type;
}
code to parse:
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
Console[] consoles = objectMapper.readValue(ResourceUtils.getFile("path of json file"), Console[].class);
logger.info("Continents -> {}",(Object)continents);
for(Console console:consoles) {
//read the data accordingly
}

How map List to an Object with list in mapstructs

How can I use MapStruct to create a mapper that maps a list (my source) to a object with a list (destination)?
My source classes looks like this:
class SourceB {
private String name;
private String lastname;
}
class SourceA {
private Integer id;
private List<SourceB> bs;
}
so I need to transform it to this:
class DestinationA {
private Integer id;
private DestinationAB bs;
}
class DestinationAB {
private List<DestinationB> b;
}
class DestinationB {
private String name;
private String lastname;
}
Expected sample json:
source:
{
"id": 1,
"bs": [
{
"name": "name1",
"lastname": "last1"
},
{
"name": "name2",
"lastname": "last2"
}
]
}
destination:
{
"id": 1,
"bs": {
"b": [
{
"name": "name1",
"lastname": "last1"
},
{
"name": "name2",
"lastname": "last2"
}
]
}
}
It's quite simple. Just put #Mapping annotation with specified source and destination on top of the mapping method.
#Mapper
public interface SourceMapper {
#Mapping(source = "bs", target = "bs.b")
DestinationA sourceAToDestinationA(SourceA sourceA);
}

Java and json object

I am trying to download a JSON file with the latest news from a link, and then fill a news page with news articles from the JSON file, but I can't get it to work.
This is my JSON file:
[
"sections": {
{
"title": "category 1",
"color": 2,
"posts": [
{
"title": "Test 1",
"date": 17-09-2019,
"images": {
"launcher_preview": "testimage.png",
"imageName2": "testimage.png"
},
"href": "https://testlink.com"
},
{
"title": "Test 2",
"date": 17-09-2019,
"images": {
"launcher_preview": "testimage2.png",
"imageName2": "testiamge2.png"
},
"href": "https://testlink2.com"
}
]
},
{
"title": "category 2",
"color": 2,
"posts": [
{
"title": "Test 3",
"date": 17-09-2019,
"images": {
"launcher_preview": "testimage3.png",
"imageName2": "testimage3.png"
},
"href": "https://testlink3.com"
}
]
}
}
]
My java class (Only included the necessary part):
public class NewsFeedManager extends ImageCache {
private static final String METADATA_URL = "https://Linkhiddenforprivacy.com/news/latest.json",
IMAGE_PROVIDER_URL = "https://Linkhiddenforprivacy.com/news/images/";
private static final int CACHE_TIME = 1000 * 60 * 20;
private final ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
#JsonProperty
#Getter
private NewsFeed feed = new NewsFeed();
private Path imageCacheDir;
public NewsFeedManager() {
}
public static NewsFeedManager load(Launcher launcher) {
NewsFeedManager manager = Persistence.load(new File(launcher.getCacheDir(), "news_feed.json"), NewsFeedManager.class);
manager.imageCacheDir = Paths.get(launcher.getCacheDir().getAbsolutePath(), "launcher/news/images");
return manager;
}
public ListenableFuture<NewsFeed> refresh(boolean force) {
if (!force && this.feed != null && this.feed.expires > System.currentTimeMillis()) {
return Futures.immediateFuture(this.feed);
}
ListenableFuture<NewsFeed> future = this.executor.submit(() -> {
log.info("Fetching latest news feed from " + METADATA_URL);
NewsFeed feed = HttpRequest.get(HttpRequest.url(METADATA_URL))
.execute()
.expectResponseCode(200)
.returnContent()
.asJson(NewsFeed.class);
feed.expires = System.currentTimeMillis() + CACHE_TIME;
return feed;
});
Futures.addCallback(future, new FutureCallback<NewsFeed>() {
#Override
public void onSuccess(#Nullable NewsFeed result) {
NewsFeedManager.this.feed = result;
NewsFeedManager.this.save();
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
});
return future;
}
public ListenableFuture<Image> getImage(String resource) {
String remote = IMAGE_PROVIDER_URL + resource;
log.info("Fetching latest image feed from " + remote);
return this.obtain(resource, remote, false);
}
private void save() {
Persistence.commitAndForget(this);
}
public void clear() {
this.feed = null;
this.clearImageCache();
}
#Override
protected long getMaxCacheTime() {
return CACHE_TIME;
}
#Override
protected Path getImageCacheFolder() {
return this.imageCacheDir;
}
public static class NewsFeed {
#JsonProperty
#Getter
private List<NewsSection> sections;
#JsonProperty
private long expires;
}
public static class NewsSection {
#JsonProperty
#Getter
private String title;
#JsonProperty
#Getter
private int color;
#JsonProperty
#JsonManagedReference
#Getter
private List<NewsPost> posts;
}
public static class NewsPost {
#JsonProperty
#Getter
private String title;
#JsonProperty
#Getter
private Date date;
#JsonProperty
#Getter
private Map<String, String> images;
#JsonProperty
#Getter
private String href;
#JsonBackReference
#Getter
private NewsSection section;
}
I get this error when the client tries to fetch the news:
[info] Fetching latest news feed from https://linkhiddenforprivacy.com/news/latest.json
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.hiddenforprivacy.launcher.ui.resources.NewsFeedManager$NewsFeed out of START_ARRAY token
at [Source: java.io.StringReader#4ac13260; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:691)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:685)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromArray(BeanDeserializerBase.java:1215)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:126)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2986)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2091)
at com.skcraft.launcher.util.HttpRequest$BufferedResponse.asJson(HttpRequest.java:479)
at com.hiddenforprivacy.launcher.ui.resources.NewsFeedManager.lambda$refresh$0(NewsFeedManager.java:61)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I am not sure what is causing the error, I think my JSON is not correctly formatted, but I am not sure, can anyone here see what is causing this error?
Thank you for your time,
Piet
If your object is in an array, you can't assign a key to it. As a result, your HttpRequest.asJson() is failing. I have edited your JSON to return your sections as an array of objects instead of a single array object containing the sections.
Also, you can't have dates as numbers in a JSON file. I converted them into strings as well. For standardization purposes, make sure you store the date as an ISO 8601 string in your actual file.
Try this edited version of your JSON:
[
{
"title": "category 1",
"color": 2,
"posts": [{
"title": "Test 1",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage.png",
"imageName2": "testimage.png"
},
"href": "https://testlink.com"
},
{
"title": "Test 2",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage2.png",
"imageName2": "testiamge2.png"
},
"href": "https://testlink2.com"
}
]
},
{
"title": "category 2",
"color": 2,
"posts": [{
"title": "Test 3",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage3.png",
"imageName2": "testimage3.png"
},
"href": "https://testlink3.com"
}]
}
]
[
"sections": {
{
I see two problems at the very start of the file.
One, the first character is a square bracket, indicating that the contained values will be a simple list. But then it goes straight into "sections" : {, which is a key/value syntax, indicating that we ought to be in a dictionary/hashmap context. But we aren't; we're in a list context.
Second, there are two opening braces following "sections":. What is the second one meant to indicate?
I see three problems
1. The wrong bracket around json object.
2. Sections is an array, but is missing the array syntax.
3. Date String is not a valid object type, the string should be wrapped with quotes.
Properly formatted json for an object with sections which is an array of two sections.
{"sections": [
{
"title": "category 1",
"color": 2,
"posts": [
{
"title": "Test 1",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage.png",
"imageName2": "testimage.png"
},
"href": "https://testlink.com"
},
{
"title": "Test 2",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage2.png",
"imageName2": "testiamge2.png"
},
"href": "https://testlink2.com"
}
]
},
{
"title": "category 2",
"color": 2,
"posts": [
{
"title": "Test 3",
"date": "17-09-2019",
"images": {
"launcher_preview": "testimage3.png",
"imageName2": "testimage3.png"
},
"href": "https://testlink3.com"
}
]
}]
}

Categories

Resources