Problem
For example, I have a list of some products in my cart like cinema ticket, carsharing and new book.
[
{
"name": "Cinema Ticket"
},
{
"name": "Car Sharing",
"properties": { ... }
},
{
"name": "New Book",
}
]
As you can see, not all products have properties.
Note: this field is polymorphic.
Question
Can I turn "non-existing" field properties into null using Jackson or it's better to change api?
And if I can then how to do that?
Jackson Version: 2.10.1
Thanks for answers!
I suppose you have something like:
public class BaseProduct {
public String name;
}
public class CarSharing extends BaseProduct {
public String properties;
}
public class Book extends BaseProduct {
}
Instead of having the properties field set to null when is not there, you can use Jackson polymorphic functionality to not show it. Something like:
#JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")
public class BaseProduct {
public String name;
}
The output would be:
[
{
"type": ".Book",
"name": "Book name"
},
{
"type": ".CarSharing",
"name": "Car share name",
"properties": "a property field"
}
]
Related
there is possibility to deserialize Json only choosen fields?
Eg:
{
"Version": 1,
"Key": "353301_PC",
"Type": "PostalCode",
"Rank": 500,
"LocalizedName": "Kleosin",
"EnglishName": "Kleosin",
"PrimaryPostalCode": "16-001",
"Region": {
"ID": "EUR",
"LocalizedName": "Europe",
"EnglishName": "Europe"
}
And i want only LocalizedName and EnglishName. Tried with objectMapper but getting errors.
Add JsonIgnoreProperties annotation to your data class
#JsonIgnoreProperties(ignoreUnknown = true)
public class YourClass {
private String LocalizedName;
private String EnglishName;
...
}
you can add #JsonIgnore to the fields inside the Region class
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;
...
I am using Swagger Core 2.0.2 for Java to generate an OpenAPI documentation. Among others, I have the following class SomeDTO:
#Schema(name = "SomeDTO", description = "some description")
public class SomeDTO {
#Schema(description = "description of name")
private String name;
#Schema(required = true, description = "description of OtherDTO")
private OtherDTO otherDTO;
}
OtherDTO is described as follows:
public class OtherDTO {
#Schema(required = true)
private String someField;
private String someOtherField;
}
My problem is that neither the description nor the required field above the otherDTO field has any effect.
The resulting openapi.json looks like this:
"components": {
"schemas": {
"SomeDTO" : {
"type": "object",
"properties": {
"name": {
"type" : "string"
}
"otherDTO" : {
"$ref": "#/components/schemas/OtherDTO"
}
},
"description": "some description"
},
"OtherDTO": {
"required": ["someField"],
"type": "object",
"properties": {
"somefield": {
"type": "string"
},
"someOtherField": {
"type": "string"
}
}
}
}
}
I was expecting the SomeDTO schema to have a required array containing OtherDTO, which it does not. The description is also lost.
I have tried numerous combinations of Schema settings, to no avail. I would highly appreciate any help to understand what I am doing wrong.
Thanks in advance.
I have found a solution to part of my problem.
The problem is caused by the fact that when using a $ref element, sibling elements are ignored. So elements (description, name etc.) related to the referenced element need to be specified as a #Schema in the referenced object itself (OtherDTO in the example above). Specifying these elements in the parent object (e.g. SomeDTO) will leave them ignored.
However, the schema elements in the referenced element do not seem to propagate up to the parent object. So, to make otherDTO a required field in SomeDTO, I need to add requiredProperties = { "OtherDTO" }) to SomeDTO's schema.
Here is the updated code:
SomeDTO
#Schema(name = "SomeDTO", description = "some description",
requiredProperties = { "OtherDTO" })
public class SomeDTO {
#Schema(description = "description of name")
private String name;
private OtherDTO otherDTO;
}
OtherDTO
#Schema(name = "OtherDTO", description = "Description of OtherDTO")
public class OtherDTO {
#Schema(required = true)
private String someField;
private String someOtherField;
}
However, it does not solve my problem completely, as I still can't figure out how to set the description of otherDTO in SomeDTO. But it gets me a step closer.
I am using spring restTemplate to map a response to a POJO.
The response of the rest api is like this:
"attributes": {
"name": {
"type": "String",
"value": ["John Doe"]
},
"permanentResidence": {
"type": "Boolean",
"value": [true]
},
"assignments": {
"type": "Grid",
"value": [{
"id": "AIS002",
"startDate": "12012016",
"endDate": "23112016"
},{
"id": "AIS097",
"startDate": "12042017",
"endDate": "23092017"
}]
}
}
in the parent class, I have:
public class Users {
private Map<String, Attribute> attributes;
}
If all the values of were String type, then I could have done like:
public class Attribute {
private String type;
private String[] value;
}
But the values are of different types. So I thought of doing the following:
public class Attribute {
private String type;
private Object[] value;
}
The above should work, but at every step I have to find out what is the type of Object.
So, my question is can I have something like this:
public class Attribute {
#JsonProperty("type")
private String type;
#JsonProperty("value")
private String[] stringValues;
#JsonProperty("value")
private Boolean[] booleanValues;
#JsonProperty("value")
private Assignments[] assignmentValues; // for Grid type
}
But it is not working and throwing errors: Conflicting setter definitions for property "value"
What is the recommended way of handling this scenario?
I would recommend Jackson facilities for handling polymorphism here:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = BooleanAttribute.class, name = "Boolean"),
#JsonSubTypes.Type(value = StringAttribute.class, name = "String")
})
class Attribute {
private String type;
}
class BooleanAttribute extends Attribute {
private Boolean[] value;
}
class StringAttribute extends Attribute {
private String[] value;
}
JsonTypeInfo tells Jackson that this is a base class and the type will be determined by a JSON field named "type"
JsonSubTypes maps subtypes of Attribute to values of "type" in JSON.
If you add an appropriate subtype for Assignments and getters/setters Jackson will be able to parse your JSON.
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.