How to ignore field depending on method? - java

How to ignore filed field depending on method?
I have a question about Spring Jackson annotations.
I have a model class. Code:
public class Tenant{
#JsonIgnore
private String id;
#JsonProperty("id")
#JsonDeserialize(using = StringValueDeserializer.class)
private String idSIMC;
#JsonProperty("name")
private String displayName;
#JsonProperty("description")
private String description;
#JsonProperty("default")
private boolean def;
#JsonProperty("geoLoc")
#JsonDeserialize(using = GeoLocationIdNameDeserializer.class)
private GeoLocation geoLoc;
#JsonProperty("asnId")
private String asnId;
#JsonProperty("devices")
#JsonDeserialize(using = StringArrayIdDeserializer.class)
private List<String> tempDevice = Collections.synchronizedList(new ArrayList<>());
#JsonIgnore
#JsonProperty("devices") // <-- I need to add this
private List<Device> devices = Collections.synchronizedList(new ArrayList());
//getters and setters...
}
Now my question. I have method#1 that instance above class and write in tempDevice IDs of devices. method#2 get all devices from servers and filter them by tempDevice (I need to do it) can I annotate ( or something else ) my fields to be ignored as Json Objects depending on method is called?
method#1
public List<Tenant> getTenantsFromServer() {
SSLVerification.disableSslVerification();
ArrayList<Tenant> tenants = new ArrayList<>(0);
String[] ids = getTenantIds();
for(int i=0; i<ids.length; i++){
ResponseEntity<ReturnUnique<Tenant>> result = getRestTemplate().exchange(getUrl() + SIEMCommands.ZONE_GET_ZONE + "?id=" + ids[i],
HttpMethod.GET, new HttpEntity(getHeader()), new ParameterizedTypeReference<ReturnUnique<Tenant>>(){});
Tenant newTenant = result.getBody().getValue();
newTenant.setParentNode(this);
newTenant.generateId();
tenants.add(newTenant);
}
return tenants;
}
In this method i have a key "devices" in that is stored id. In method#2 another json that also have "devices" key but with another dates.(name,ip, etc.) And when I execute this method I should to store all in devices list.
JSON used in first method#1
{"return": {
"asnId": 0,
"default": false,
"description": "",
"devices": [
{"id": 144121785900597248},
{"id": 144121785917374464},
{"id": 144121785934151680}
],
"geoLoc": {
"id": {"value": 0},
"name": ""
},
"id": {"value": 1},
"name": "HA_Zone"
}}
devices values are written in tempDevice;
method#2 use this JSON
"devices": [{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.60.17",
"ipsID": "144121785950928896",
"ipsRight": true,
"name": "ASA Admin CTX Site 2",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "6",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "49",
"vipsInSync": false
},
{
"CRuleRight": true,
"FTestRight": true,
"adRight": true,
"addDeleteRight": false,
"children": [],
"clientCount": 0,
"clientStatus": "0",
"clientVipsInSync": false,
"deviceActionRight": true,
"deviceDisabled": false,
"elmFile": false,
"elmHasSAN": false,
"eventRight": true,
"hostname": "",
"ipAddress": "172.28.13.10",
"ipsID": "144121785179176960",
"ipsRight": true,
"name": "ASA-VPN-DC1",
"parent": false,
"polRight": true,
"protocol": "gsyslog",
"reportRight": true,
"status": "0",
"statusAck": "0",
"tpcCollector": "syslog",
"tpcType": "278",
"type": "VIPS",
"viewRight": true,
"vipsEnabled": true,
"vipsID": "3",
"vipsInSync": false
}
}]
this dates i have to write in devices

If I understand correctly, you are looking for a way to deserialize 2 different json datatype having same property name into a object in different situation. If that is the case, the suggestion of using JacksonMixInAnnotations from #Thomas should work. JacksonMixInAnnotations can provide a kind of way to add annotation from another class (called mix-in class) to the target class during run time.
In your case, you can left tempDevice and devices without Jackson annotation like follows:
public class Tenant {
private List<String> tempDevice;
private List<Device> devices;
}
and declare 2 mix-in classes:
abstract class TempDeviceMixIn {
#JsonProperty("devices")
private List<String> tempDevice;
}
abstract class DeviceMixIn {
#JsonProperty("devices")
private List<Device> devices;
}
When you need to deserialize a json string with a string property of devices, you can add mix-in class annotation likes:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Tenant.class, TempDeviceMixIn.class);
Tenant tenant = mapper.readValue(json, Tenant.class);
Deserialize a json string with a object property of devices is similar.
As you are using RestTemplate, you will need a MappingJacksonHttpMessageConverter with your ObjectMapper.

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

Jackson deserializing json choosen fields

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

Hide controller parameter in Swagger documentation

I'm using swagger-jersey2-jaxrs to generate swagger.json. This is my java code:
#Path("/example")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#ApiImplicitParams({
#ApiImplicitParam(name = "object", required = true, dataTypeClass = MyObject.class, paramType = "body")
})
#ApiOperation(value = "Return one entity", notes = "Returns one entity at random", response = CommonResponse.class)
public String getStuff(String requestString) {...}
And I got this swagger.json file as the result:
"parameters": [
{
"in": "body",
"name": "body", // SHOULD BE REMOVED
"required": false,
"schema": {
"type": "string"
}
},
{
"in": "body",
"name": "object", // I ONLY WANT THIS
"required": true,
"schema": {
"$ref": "#/definitions/MyObject"
}
}
]
As I know String requestString will generate parameter name="body" by default. How can I remove it? I just want my parameter name="object" to be appeared.
By using #ApiParam annotation from io.swagger.annotations you can hide parameters. To do this, set the field hidden to true.
...
public String getStuff(
#ApiParam(hidden = true) String requestString) {...}

Jackson Json to POJO mapping

i am i little lost in creating a mapping with jackson. My Json has the following structure
{
"d": {
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/JobApplication(1463L)",
"type": "SFOData.JobApplication"
},
"lastName": "K",
"address": "123 Main Street",
"cellPhone": "12345",
"firstName": "Katrin",
"city": "Anytown",
"country": "United States",
"custappattachment": {
"results": [
{
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/Attachment(1188L)",
"type": "SFOData.Attachment"
},
"fileExtension": "jpeg",
"fileName": "hp-hero-img.jpeg",
"fileContent": "/9j/4AA"
},
{
"__metadata": {
"uri": "https://apisalesdemo8.successfactors.com:443/odata/v2/Attachment(1189L)",
"type": "SFOData.Attachment"
},
"fileExtension": "jpeg",
"fileName": "hp-content-bkgd-img.jpeg",
"fileContent": "/9j/4AAQSk"
}]}}}
I do find a lot of tutorials handling arrays, but i fail already with the very first token "d".
and all the "__metadata" token are not needed at all.
I created a pojo containing attributes like lastName etc. and a collection attachments.
But my code always fails at token "d" or "__metadata"
public class ResponseDataObject {
private String lastName;
private String address;
private String cellPhone;
private String firstName;
private String city;
private String country;
private List<Attachment> attachments = new ArrayList<>();
.....getters and setters
and the jackson reader
ObjectReader objectReader =
mapper.readerFor(ResponseDataObject.class);
ResponseDataObject dataObject = objectReader.readValue(file);
Any hints would be appreciated.
Regards
Mathias
You can use #JsonIgnoreProperties annotation to ignore the properties that don't match any of the members defined in class, e.g.:
#JsonIgnoreProperties(ignoreUnknown = true)
public class ResponseDataObject {
This will make sure all the matching properties are mapped and other properties are ignored.
You need to ignore properties, not present in POJO. Set following property in DeserializationFeature for ObjectMapper:
// for version 1.x
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// for newer versions
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Deserialization code:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
ResponseDataObject dataObject = mapper.readValue(file, ResponseDataObject.class);
and add this annotation to ResponseDataObject class:
#JsonRootName(value = "d")
class ResponseDataObject {

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