JsonPropertyOrder not ordering correctly - java

so as you can see from the title my #JsonPropertyOrder is not ordering how I want... this is my class(see code bellow) and everything is ordered good except the zpp attribute, it goes between "spravce" and "ziskatele". I tried to rename it reorder it and its totally ignored.Thank you for all the answers :)
(JacksonXML ver 2.9.8)
#JacksonXmlRootElement(localName = "xmlroot")
#JsonPropertyOrder({"cnt-unik-id","kod-produktu","frekvence","datum-sjednani",
"pocatek","konec","spravce","ziskatele","objekty-unik-id","udaje","objekty-all","adresy","zpp"})
public class ContractDetail{
#JacksonXmlProperty(localName = "zpp")
private Integer zpplID;
#JacksonXmlProperty(localName = "cnt-unik-id")
private Integer id;
#JacksonXmlProperty(localName = "kod-produktu")
private Item product;
#JacksonXmlProperty(localName = "spravce")
private Item administrator;
#JacksonXmlElementWrapper(localName = "ziskatele")
#JacksonXmlProperty(localName = "xml-ziskatel")
private List<Customer> customers;
#JacksonXmlProperty(localName = "frekvence")
private Item frequency;
#JacksonXmlProperty(localName = "datum-sjednani")
private Item createdAt;
#JacksonXmlProperty(localName = "pocatek")
private Item startDate;
#JacksonXmlProperty(localName = "konec")
private Item endDate;
#JacksonXmlElementWrapper(localName = "objekty-unik-id")
#JacksonXmlProperty(localName = "int")
private List<Integer> vehicle;
#JacksonXmlProperty(localName = "xml-hodnota")
#JacksonXmlElementWrapper(localName = "udaje")
private List<Item> values;
#JacksonXmlProperty(localName = "xml-objekt")
#JacksonXmlElementWrapper(localName = "objekty-all")
private List<ObjectItem> objects;
#JacksonXmlElementWrapper(localName = "adresy")
#JacksonXmlProperty(localName = "xml-adresa")
private List<AddressItem> address;
//getters setters contructors stuff
}

Use the Java field names, instead of the XML element names.
For example, using a simplified version of your ContractDetail class:
Using this:
#JsonPropertyOrder({"id", "vehicle", "zpplID"})
Generates this:
<xmlroot>
<cnt-unik-id>123</cnt-unik-id>
<objekty-unik-id>
<int>678</int>
<int>789</int>
</objekty-unik-id>
<zpplID>456</zpplID>
</xmlroot>
And using this:
#JsonPropertyOrder({"vehicle", "zpplID", "id"})
Generates this:
<xmlroot>
<objekty-unik-id>
<int>678</int>
<int>789</int>
</objekty-unik-id>
<zpplID>456</zpplID>
<cnt-unik-id>123</cnt-unik-id>
</xmlroot>

Soo #andrewjames's answer works but If someone still needs/wants to use xml element names the solution I came up with looks like this:
#JsonPropertyOrder({"cnt-unik-id","kod-produktu","frekvence","datum-sjednani",
"pocatek","konec","spravce","ziskatele","objekty-unik-id","int","udaje","xml-hodnota","objekty-all","xml-objekt","adresy","xml-adresa","zpp"})

Related

How to put CollectionAttribute<A, B> into collection like List<B> when retrieving A with Criteria API?

We have an object that works as the DTO and is returned by the method using criteria API:
public class ServiceMobileData {
private int id;
private String name;
private String image;
private List<String> prefixes;
private int categoryId;
private boolean available;
private boolean additionalFields;
private boolean multiFields;
public ServiceMobileData(int id, String name, String image, int categoryId, boolean available,
boolean additionalFields, boolean multiFields, List<String> prefixes) {
this.id = id;
this.name = name;
this.image = image;
this.categoryId = categoryId;
this.available = available;
this.additionalFields = additionalFields;
this.multiFields = multiFields;
this.prefixes = prefixes;
}
...}
please note private List<String> prefixes;
We have two entities:
public class ServiceEntity {
#Id
private Integer id;
#Column(nullable = false, length = 100)
private String name;
..
#OneToMany(mappedBy = "service")
private Collection<ServicePrefixEntity> servicePrefixes;
}
and
#Entity
#Table(name = "service_prefixes")
public class ServicePrefixEntity {
#Id
private Integer id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "service_id")
private ServiceEntity service;
..
#Column(name = "validation_prefix")
private String validationPrefix;
}
With Criteria API I retrieve the columns from the ServiceEntity like that:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ServiceMobileData> c = cb.createQuery(ServiceMobileData.class);
Root<ServiceEntity> serviceRoot = c.from(ServiceEntity.class);
c.multiselect(serviceRoot.get(ServiceEntity_.id),
serviceRoot.get(ServiceEntity_.name),
...
);
TypedQuery<ServiceMobileData> q = em.createQuery(c);
return q.getResultList();
Currently in multiselect() there is no query to retrieve the collection of ServiceEntityPrefix, as adding in the corresponding last position of multiselect wouldn't work. What I should do to include serviceRoot.get(ServiceEntity_.servicePrefixes) to multiselect? I'd like to extract only one String parameter (namely validationPrefix) from the ServicePrefixEntity and pass a collection of them to the DTO object during the return q.getResultList();, should I add this entity to join too? And how I can put those values into collection? Is it ever possible?
Currently it was resolved, but not yet as I really wanted that with putting the collection into the multiselect() and then to the constructor.
add the subquery
Subquery<String> prefixSubquery = c.subquery(String.class);
Root<ServicePrefixEntity> prefixRoot =
prefixSubquery.from(ServicePrefixEntity.class);
prefixSubquery.select(prefixRoot.get(ServicePrefixEntity_.validationPrefix));
prefixSubquery.where(cb.equal(prefixRoot.get(ServicePrefixEntity_.serviceId),serviceRoot.get(ServiceEntity_.id)));
put its' output as a separate parameter into mulstiselect and adjust the returned object type constructor accordingly:
c.multiselect(serviceRoot.get(ServiceEntity_.id),
serviceRoot.get(ServiceEntity_.name),
...
prefixSubquery.getSelection()
);
and
public ServiceMobileData(int id, String name, ... String mask) {
this.id = id;
this.name = name;
...
this.mask = mask;
}
What I still missing is how it is possible to instantiate subquery like that:
Subquery<String> prefixSubquery = c.subquery(List.class, String.class);
i.e. to put the result being saved to the objects collection

Serialization with Jackson XmlMapper

I'm trying to serialize object to xml string with Jackson XmlMapper. My object is:
#JacksonXmlRootElement(namespace = "http://www.w3.org/2001/XMLSchema", localName = "PersonRO")
public class PersonInfo {
#JacksonXmlProperty(localName = "PersonID")
private String personId;
#JacksonXmlProperty(localName = "ReturnCode")
private Integer errorCode;
// getters, setters
}
I need to achieve following xml in output:
<PersonRO xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<PersonID>00000000000001</PersonID>
<ReturnCode>150</ReturnCode>
</PersonRO>
The task seems easy, but first of all I have a problem with achieving multiple namespases (xmlns:xsd, xmlns:xsi), and also have empty namespaces for fields, although I don't need them at all.
So far my result is:
<PersonRO xmlns="http://www.w3.org/2001/XMLSchema">
<PersonID xmlns="">00000000000001</PersonID>
<ReturnCode xmlns="">150</ReturnCode>
</PersonRO>
So, how can I achieve exactly the same result as above, using Jackson XmlMapper?
(I've seen that you can configure XmlFactory, etc., but can not do it properly...)
If you need any clarification, please let me know and thank you in advance.
I have found the answer:
#JacksonXmlRootElement(localName = "PersonRO")
public class PersonInfo {
#JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsd")
private final String xmlnsXsd = "http://www.w3.org/2001/XMLSchema";
#JacksonXmlProperty(isAttribute = true, localName = "xmlns:xsi")
private final String xmlnsXsi = "http://www.w3.org/2001/XMLSchema-instance";
#JacksonXmlProperty(localName = "PersonID")
private String personId;
#JacksonXmlProperty(localName = "ReturnCode")
private Integer errorCode;
// getters, setters
}

Jackson XML with different element name and attributes under root tag

I'm new to Jackson XML and I have a requirement of constructing a Jackson XML with different element name and attributes but under same root element.
My Expected xml output
<item name="Whatever">
<problem_id id="12312"/>
<problem_type type="1765"/>
<problem_desc desc="faulty"/>
</item>
My pojo class ( Not sure how to add the remaining elements and attributes)
#JacksonXmlRootElement(localName = "item")
public class ItemsDTO {
#JacksonXmlProperty(localName = "name",isAttribute = true)
private String name="Whatever";
}
Any advise would be much appreciated.
To do this, you may need to implement more classes like you have already done and then add related properties to your container class ItemsDTO:
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
#JacksonXmlRootElement(localName = "item")
public class ItemsDTO {
#JacksonXmlProperty(isAttribute = true)
private String name = "Whatever";
#JacksonXmlProperty(localName = "problem_id")
private ProblemId problemId = new ProblemId();
#JacksonXmlProperty(localName = "problem_type")
private ProblemType problemType = new ProblemType();
#JacksonXmlProperty(localName = "problem_desc")
private ProblemDesc problemDesc = new ProblemDesc();
}
class ProblemId {
#JacksonXmlProperty(isAttribute = true)
private int id = 12312;
}
class ProblemType {
#JacksonXmlProperty(isAttribute = true)
private int type = 1765;
}
class ProblemDesc {
#JacksonXmlProperty(isAttribute = true)
private String desc = "faulty";
}
Although it would be better to have a shorter XML output with problem's properties "encapsulated" in a single element like this:
<item name="Whatever">
<problem id="12312" type="1765" desc="faulty"/>
</item>
This can be achieved with the following code:
#JacksonXmlRootElement(localName = "item")
public class ItemDTO {
#JacksonXmlProperty(isAttribute = true)
private String name = "Whatever";
#JacksonXmlProperty
private Problem problem = new Problem();
}
class Problem {
#JacksonXmlProperty(isAttribute = true)
private int id = 12312;
#JacksonXmlProperty(isAttribute = true)
private int type = 1765;
#JacksonXmlProperty(isAttribute = true)
private String desc = "faulty";
}

Spring Cassandra store a List with custom object's

I like to store a object like:
#Table(value = "my_table")
public class MyTableDto {
#PrimaryKeyColumn(name = "uid", type = PrimaryKeyType.PARTITIONED)
#CassandraType(type = DataType.Name.UUID)
private UUID uid;
#Column(value = "child_ids")
private List<ChildIdDto> childIds;
}
Then I get the exception:
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Only primitive types are allowed inside Collections for property [childIds] of type ['interface java.util.List'] in entity [de.myapplication.repository.dto.MyTableDto]
I do understand the exception, but is there another way to persist custom objects?
EDIT:
When I comment out this attribute, everything works
! Never say never, I got the solution.
To give a good example, I will list all according classes.
ParentClass.java
#Table(value = "my_table") //OPT
public class MyTableDto {
#PrimaryKeyColumn(name = "uid", type = PrimaryKeyType.PARTITIONED)
#CassandraType(type = DataType.Name.UUID)
private UUID uid;
#Column(value = "child_ids") //OPT
private List<ChildDto> childIds;
}
ChildDto.java
#UserDefinedType // THE SOLUTION
public class ChildDto {
#Column(value = "child") //OPT
#CassandraType(type = DataType.Name.TEXT) //OPT
private String groupId;
#Column(value = "description") //OPT
#CassandraType(type = Name.TEXT) //OPT
private String description;
}
The #UserDefinedType is the solution.
For more information see here.
NOTE: Each annotation with "OPT" is NOT required

Serialize JSON Subclasses Information in Java

I need some help with one JSON serialization Problem.
I have one class like this:
#Entity
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
#DiscriminatorFormula("type")
#JsonSubTypes({ #JsonSubTypes.Type(value =TextFileCardEntity.class, name = "textCard"),
#JsonSubTypes.Type(value = MultipleChoiceFileCard.class, name = "choiceCard")#JsonSubTypes.Type(value = MultipleChoiceFileCard.class, name = "choiceCard")})
public class FileCardEntity extends ResourceEntity implements Cloneable {
#NotNull
#JsonIgnore
private FileCardType type;
private Date expirationDate;
.....
I also have two classes that extends of FileCardEntity:
#JsonTypeName(value = "textCard")
public class TextFileCardEntity extends FileCardEntity {
#Lob
#Type(type = "org.hibernate.type.TextType")
private String question;
#Lob
#Type(type = "org.hibernate.type.TextType")
private String answer;
.......
AND
#Entity
#DiscriminatorValue("1")
#JsonTypeName(value = "choiceCard")
public class MultipleChoiceFileCard extends FileCardEntity {
#Lob
#Type(type = "org.hibernate.type.TextType")
private String question;
#Lob
#Type(type = "org.hibernate.type.TextType")
private String crib;
......
I use the next Code in order to deserialize the information:
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
final ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, classElement));
System.out.println(typedWriter.writeValueAsString(elements));
Where elements is: List<?> elements
When I deserialize information from Server about TextFileCardEntity, I get:
[{"textCard":{"status":"ACTIVE","lastModified":1366293513200,"expirationDate":0.....
That is ok
When I attempt serialize information about TextFileCardEntity for example to Server, the code sends:
[{"FileCardEntity":{"status":"ACTIVE","lastModified":1366378327069,"shared":false,"orderID":0........
That is not ok because I need the syntax to be similar has in the deserialization information
--> [{"textCard":{"status".... and not [{"FileCardEntity":{"status"....
What can I do?

Categories