Trouble mapping XML to a list of POJOs in Jackson - java

I need to take XML that looks like something like the following:
<root:ElementName>
<equipment:Equipment>
<eqp:Name>Equipment 1</eqp:Name>
<eqp:Type>A</eqp:Type>
</equipment:Equipment>
<equipment:Equipment>
<eqp:Name>Equipment 2</eqp:Name>
<eqp:Type>B</eqp:Type>
</equipment:Equipment><equipment:Equipment>
<eqp:Name>Equipment 3</eqp:Name>
<eqp:Type>C</eqp:Type>
</equipment:Equipment>
</root:ElementName>
And I want to map that into a list of "Equipment" POJOs. I'm using Jackson XML mapping and Lombok, so basically I've got this split into two classes right now, first the root object which should read in that <root:ElementName> and turn all the <equipment:Equipment> tags into a list of equipment objects:
#JacksonXmlRootElement(localName = "root:ElementName")
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public class EquipmentMidbCompositeResponse
{
#JsonProperty("equipment")
#JacksonXmlProperty(localName = "equipment:Equipment")
#Getter
#Setter
List<Equipment> equipmentList;
}
And then the Equipment object itself:
#Entity
#Data
#NoArgsConstructor
#EqualsAndHashCode(callSuper = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
public final class Equipment
{
#JsonCreator
public Equipment(String name){
}
#JsonProperty("EquipmentName")
#JacksonXmlProperty(localName = "eqp:Name")
#Setter
#Getter
private String name;
#JsonProperty("EquipmentType")
#JacksonXmlProperty(localName = "eqp:Type")
#Setter
#Getter
private String type;
}
At first I didn't have that constructor with #JsonCreator in the Equipment object and would get a "no String-argument constructor/factory method to deserialize from String value" error, and after some research added the constructor to get around that. With that I get past that error, but the list of Equipment objects that gets returned after mapping have all their fields set to null. What am I missing/doing wrong here when trying to map these XML properties?

(Posted on behalf of the OP).
I figured out the issue, my approach with the #JsonCreator was the incorrect way to go for that error. Turns out all I had to do was an a #JacksonXmlElementWrapper(useWrapping=false) annotation to my list item and everything went through just fine.

Related

Null Values are assigned as values for a list in POJO SpringBoot/Java

I have a POJO that will be reading the data from a Kafka Consumer. I have a couple of list objects inside it and I am not able to understand the Null behavior of it
EmployeeEBO.java
#Getter
#Setter
#Builder
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
#NoArgsConstructor
#AllArgsConstructor
public class EmployeeEBO implements Serializable {
private static final long serialVersionUID = 1L;
private String EmpId;
private List<AssignedWorkEBO> assignedWorks;
}
AssignedWorkEBO.java
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#SuperBuilder(toBuilder = true)
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class AssignedWorkEBO{
private String assignedWorkType;
private String assignedWorkId;
}
So I am trying to Check whether the data from kafka is Empty/Null condition for the AssignedWorkEBO and it behaves odd
When the pojo is printed
Received Payload from kafka: {"Employee":{"EmployeeId":"E2212","assignedWorks":[{}]}}
But when i check for isempty it throws fals
log.info("employee.getAssignedWorks().isEmpty();" + employee.getAssignedWorks().isEmpty());//false
log.info("employee.getAssignedWorks().size();" + employee.getAssignedWorks().size()); //1
so it should be ideally true for is empty and zero for size
Received Payload from kafka: {"Employee":{"EmployeeId":"E2212","assignedWorks":[{"assignedWorkId":"34241"}]}}
this is ok as it has values it is giving me correct
log.info("employee.getAssignedWorks().isEmpty();" + employee.getAssignedWorks().isEmpty());//false
log.info("employee.getAssignedWorks().size();" + employee.getAssignedWorks().size()); //1
But why the Null is coming as value. Is that due to any jackson annotations I Used ?
Please advise
Thanks
The result you obtained is correct.
For your {"EmployeeId":"E2212","assignedWorks":[{}]}} input json it is correct that employee.getAssignedWorks().isEmpty() returns false and employee.getAssignedWorks().size() return 1. The assignedWorks field is a json array containing an empty object so it will be serialized to the assignedWorks list in your pojo as a list containing one work with all null fields.

Spring Boot ConfigurationProperties - Base Class is not mapped

I am trying to setup a spring-boot configuration that uses different properties which have the same base class. The problem is that the base type is always null.
I am doing this because I want have different configuration elements that have a set of required properties and also have some additional properties .
For context: The configuration file looks as follows and is saved as JSON:
{
// some other properties
"layout": {
"test": 1,
"element": {
"#type": "traffic",
"id": "id-1",
"district": "district"
}
}
For this layout property I use the following class:
#ConfigurationProperties(prefix = "layout")
#ToString
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class LayoutProperties {
/* This is always correct */
private int test;
/* This is always null! */
private LayoutObject element;
}
The base class looks a follows:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY
)
#JsonSubTypes({
#JsonSubTypes.Type(value = TrafficLayoutObject.class, name = "traffic"),
})
public abstract class LayoutObject {
public abstract String getId();
}
where I use the #JsonTypeInfo and the #JsonSubTypes annotations as suggested in some tutorials.
An implementation of this class is this one:
#ConstructorBinding
#ToString
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class TrafficLayoutObject extends LayoutObject {
private String id;
private String district;
}
which essentially adds an additional district field.
The problem now is that whenever I startup my application the elements field if declared as LayoutObject is null. However, when using the specific type (e.g. TrafficLayoutObject) the field is filled properly by spring.
Another interesting thing is that Jackson seems to handle this correctly because when deserializing the layout object from the config, everything is filled correctly.
What am I missing? Or is there a better way to do this?

How to exclude boolean type value for jackson payload

I have really simple requirement to exclude Boolean type attribute from payload during Jackson serialization. Following is the piece of code that I want to fix that. I want exclude it always irrespective to its value.
#Getter
#Setter
#NoArgsConstructor
#XmlRootElement
public class Order{
#JsonIgnore
private boolean userPresent;
}
Can someone help me on this?
You should explicitly add the Getter for the property you want to ignore and set the #JsonIgnore there:
#Getter
#Setter
#NoArgsConstructor
#XmlRootElement
public class Order{
private boolean userPresent;
#JsonIgnore
public boolean isUserPresent() {
return this.userPresent;
}
}
If you don't have any other properties in the class, you should remove the #Getter annotation because it is redundant now.

Get Mongo db id after insertion in case of POJO class

I have a POJO class in java
#Data
#EqualsAndHashCode(callSuper = false)
#NoArgsConstructor
#AllArgsConstructor
public class TestModel{
protected ObjectId id;
private String name;
}
Is there any way to populate id field in case of insertion. I can see that if I use Document, then after insertion I can get objectId by using
document.get("_id");
So is there any way I can achieve same using custom POJO class.

Add validation rules to Pojo.name to object extending Pojo?

I have a simple java pojo which i give to my android users:
#XmlRootElement
#AllArgsConstructor
#NoArgsConstructor
#ToString
public class PostAccount {
#Getter
#Setter
private String email;
#Getter
#Setter
private String pass1;
#Getter
#Setter
private String pass2;
}
This pojo is serialized to json and send to my server. On my server i which to use jersey bean validation:
public NumberResult add(#Valid ValidAccount account) {
But because the Account pojo doesn't have any validation annotations validation doesn't do much.
I can create a second pojo with validation annotations and use that on server side:
public class ValidAccount {
#Getter
#Setter
#NotEmpty
#CheckEmail
private String email;
#Getter
#Setter
#NotBlank
private String pass1;
#Getter
#Setter
#NotBlank
private String pass2;
}
Works perfectly.
But when i now add a field at Account pojo i do have to remember to change ValidAccount pojo. No problem, but when you have a lot of pojo's things get complicated to manage.
Is there a better solution?
For example is it possible to extends the Account pojo and in a way add the validation rules? (please i which to continue using annotations, xml gives me the creeps)

Categories