Unable to access profilePicture JSON parameter in LinkedIn profile response (Java) - java

I am trying to retrieve the profilePicture parameter in the LinkedIn liteProfile response. However, for some reason, they return two json objects with the same parameter name (Who even built this API?!).
Response:
{
"firstName": {
"localized": {
"en_US": "Damien"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"lastName": {
"localized": {
"en_US": "Roger"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"profilePicture": {
"displayImage": "urn:li:digitalmediaAsset:C5103AQEGbbhK9i7Qhw",
"displayImage~": {
"paging": {
"count": 10,
"start": 0,
"links": []
},
"elements": [
{
"identifiers": [
{
"identifier": "https://media.licdn.com/dms/image/C5103AQEGbbhK9i7Qhw/profile-displayphoto-shrink_200_200.....",
....
}
}
]
}
}
}
As you may have noticed, in profilePicture, there's two params called displayImage. One with a ~. How do I access this from a java pojo class?
My class looks like this:
public class LinkedInProfileResponse {
public FirstName firstName;
public LastName lastName;
public ProfilePicture profilePicture;
public String id;
public class ProfilePicture {
public String displayImage;
public DisplayImage displayImage;
}
}

The #SerializedName annotation can be used on a field in your POJO to specify the name of the JSON attribute to be mapped to the Java field.
So in your case:
...
#SerializedName("displayImage~)
public DisplayImage displayImage;
...

Related

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"
}
]
}]
}

Convert a Dynamic JSON String to a HashMap

I have a JSONObject with some dynamic attributes that I want to convert into a class, I have tried a lot of examples on SO, but no solution.
My json string looks like this
{
"result": {
"account": "rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q",
"assets": {
"r9F6wk8HkXrgYWoJ7fsv4VrUBVoqDVtzkH": [
{
"currency": "BTC",
"value": "5444166510000000e-26"
}
],
"rPFLkxQk6xUGdGYEykqe7PR25Gr7mLHDc8": [
{
"currency": "EUR",
"value": "4000000000000000e-27"
}
],
"rPU6VbckqCLW4kb51CWqZdxvYyQrQVsnSj": [
{
"currency": "BTC",
"value": "1029900000000000e-26"
}
],
"rpR95n1iFkTqpoy1e878f4Z1pVHVtWKMNQ": [
{
"currency": "BTC",
"value": "4000000000000000e-30"
}
],
"rwmUaXsWtXU4Z843xSYwgt1is97bgY8yj6": [
{
"currency": "BTC",
"value": "8700000000000000e-30"
}
]
},
"balances": {
"rKm4uWpg9tfwbVSeATv4KxDe6mpE9yPkgJ": [
{
"currency": "EUR",
"value": "29826.1965999999"
}
],
"ra7JkEzrgeKHdzKgo4EUUVBnxggY4z37kt": [
{
"currency": "USD",
"value": "13857.70416"
}
]
},
"ledger_hash": "980FECF48CA4BFDEC896692C31A50D484BDFE865EC101B00259C413AA3DBD672",
"ledger_index": 14483212,
"obligations": {
"BTC": "5908.324927635318",
"EUR": "992471.7419793958",
"GBP": "4991.38706013193",
"USD": "1997134.20229482"
},
"status": "success",
"validated": true
}
}
Is there something that I can use from the json.org or ObjectMapper?
The only part that is given me problem is the assets and the balances, I will appreciate all help in right direction
You should be able to deserialize this into classes like:
public class Response {
private Result result;
}
public class Result {
private String account;
private Map<String, List<Asset>> assets;
private Map<String, List<Asset>> balances;
private String ledger_hash;
private String ledger_index;
private Map<String, String> obligations;
private String status;
private boolean validated;
}
public class Asset {
private String currency;
private String value;
}

katharsis collection of non primitives serialization

Trying to serialize a collection of non-primitive types using katharsis, but getting an empty collection all the time.
Response example:
{
"data": {
"type": "products",
"id": "1",
"attributes": {
"simpleAttributes": [
{}
],
"variationGroup": "variationGroup"
},
"relationships": {},
"links": {
"self": "http://localhost:8080/api/products/1"
}
},
"included": []
}
Expected response:
{
"data": {
"type": "products",
"id": "1",
"attributes": {
"simpleAttributes": [
{
tittle: "some title",
value: "some value"
}
],
"variationGroup": "variationGroup"
},
"relationships": {},
"links": {
"self": "http://localhost:8080/api/products/1"
}
},
"included": []
}
Domain objects (getters, setters, constructor and other stuff omitted by using lombok #Data annotation):
#JsonApiResource(type = "products")
#Data
public class Product {
#JsonApiId
private Integer id;
private List<SimpleAttribute> simpleAttributes = new ArrayList<>();
private String variationGroup;
}
#Data
public class SimpleAttribute implements Serializable{
private String title;
private String value;
}
I do not want to use relationships in this case or to include attributes to "included" field. Is it possible in katharsis?
Not sure what actually was wrong, but the problem disappeared after I changed katharsis-spring version from 2.3.0 to 2.3.1.

Categories

Resources