Jackson XML Parsing - java

Jackson 2.2.3
First, please excuse the stupid mistakes, I'm on a disconnected network, so I had to retype manually)
I have the following XML:
<orgs>
<org name="Test1">
<item>a</item>
<item>b</item>
</org>
<org name="Test2">
<item>c</item>
<item>d</item>
<item>e</item>
</org>
</orgs>
I have the following class to parse this:
#XmlRootElement(name = "orgs")
#XmlAccessorType(XmlAccessType.FIELD)
public class XmlOrgElements {
private List<Org> orgs;
public List<Org> getOrgs() {
return orgs;
}
public void setOrg(List<Org> orgs) {
this.orgs = orgs;
}
public class Org {
#JacksonXmlProperty(isAttribute = true)
private String name;
private List<Item> items;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Item> getItems() {
return items;
}
public void setName(List<Item> items) {
this.items = items;
}
}
public class Item {
#JacksonXmlText
private String item;
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
}
}
But all I'm getting back is "orgs=null". Does anyone know why?

You need to enable unwrapped handling for lists; default is to use "wrapped" format. The best way to diagnose this problem is to start with Java objects, serialize as XML, and see what the output format is.
This gives an idea of how structure differs.
If you want to default to unwrapped style, you can use:
JacksonXmlModule module = new JacksonXmlModule();
module.setDefaultUseWrapper(false);
mapper.registerModule(module);
There is also an annotation #JacksonXmlElementWrapper:
public class Bean {
#JacksonXmlElementWrapper(useWrapping=false)
public List<Stuff> entry;
}
to change behavior on per-list-property basis.

Here is the answer for those reading along:
#JacksonXmlRootElement(localname = "orgs")
public class Orgs {
#JacksonXmlElementWrapper(useWrapping = false)
private List<Org> org;
public List<Org> getOrg() {
return org;
}
public void setOrg(List<Org> org) {
this.orgs = org;
}
public Orgs() {}
}
public class Org {
#JacksonXmlProperty(isAttribute = true)
private String name;
#JacksonXmlElementWrapper(useWrapping = false)
private List<String> item;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getItem() {
return item;
}
public void setItem(List<String> item) {
this.item = item;
}
}

Related

Expected END_ELEMENT, got event of type 1 (through reference chain: ...->java.util.ArrayList[0])

I'm using XMLMapper to deserialize AIML code (mostly the same as XML) and got this problem when I mix text and tags under the same tag. Example:
<set name="setVar">
<srai>FUNCTION1</srai>
<srai>FUNCTION2<star index="1"/></srai>
</set>
My java classes definition are:
#JacksonXmlRootElement(localName = "set")
public class Set {
#JacksonXmlProperty(isAttribute = true, localName = "name")
public String name;
#JacksonXmlElementWrapper(useWrapping = false)
#JacksonXmlProperty(localName = "srai")
public List<Srai> srais;
public Set() {
}
public Set(String name, List<Srai> srais) {
this.name = name;
this.srais = srais;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Srai> getSrais() {
return srais;
}
public void setSrais(List<Srai> srais) {
this.srais = srais;
}
}
#JacksonXmlRootElement(localName = "srai")
public class Srai {
#JacksonXmlElementWrapper(useWrapping = false)
#JacksonXmlProperty(localName = "star")
public List<Star> stars;
#JacksonXmlText
public String text;
public Srai() {}
public Srai(String text, List<Star> stars) {
this.text = text;
this.stars = stars;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public List<Star> getStars() {
return stars;
}
public void setStars(List<Star> stars) {
this.stars = stars;
}
}
#JacksonXmlRootElement(localName = "star")
public class Star {
#JacksonXmlProperty(isAttribute = true)
public int index;
public Star() {
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
If I try to deserialize code in which there are only text or only stars into the srai, everything works perfect, the problem appears when I mix text and tags.
I finally managed to solve it upgrading my jackson-databind, jackson-core, jackson-annotation and jackson-dataformat-xml to the version 2.12.1 as tnci suggested here.
To do this, just change their version into the pom.xml to 2.12.1 or later versions.
Then I created a new property into the star class:
#JacksonXmlText
public String text;
This way, when there is text before or between xml tags, it will be saved in this property on a star object. If the text is after all xml tags, there will appear this problem:
Unexpected end-of-input when trying read value of type `**root-agent-class**`
So the problem persists but now it's much better since we can read some text+tags code.

SAXParser parse complex object

I am a novice in SAXParser. I don't know is it possible to parse complex object with SAXParser. I have a class which contain Item list. And my response xml is like that :
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetPaymentServiceInfoResponse xmlns="http://quetzalcoatlus/EpulPaymentService"><GetPaymentServiceInfoResult><ResultCodes>OK</ResultCodes><Description>User is temporary blocked</Description><Items><Item><Amount>122</Amount></Item><Item><Amount>23232</Amount></Item></Items></GetPaymentServiceInfoResult></GetPaymentServiceInfoResponse></s:Body></s:Envelope>
And my POJO class is like following:
#XmlRootElement(name = "PGResponse")
public class CheckAbonSuccessResponseModel {
private String message;
private String message_code;
private BigDecimal amount;
private String invoiceCode;
private String operationCode;
private List<Item> items;
#XmlElement(name = "message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
#XmlElement(name = "message_code")
public String getMessage_code() {
return message_code;
}
public void setMessage_code(String message_code) {
this.message_code = message_code;
}
#XmlElement(name = "amount")
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
#XmlElement(name = "invoice_code")
public String getInvoiceCode() {
return invoiceCode;
}
public void setInvoiceCode(String invoiceCode) {
this.invoiceCode = invoiceCode;
}
#XmlElement(name = "operation_code")
public String getOperationCode() {
return operationCode;
}
public void setOperationCode(String operationCode) {
this.operationCode = operationCode;
}
#XmlElement(name = "items")
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
#XmlRootElement(name = "item")
public static class Item {
private String label;
private String value;
#XmlElement(name = "label")
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#XmlElement(name = "value")
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
How I can parse my xml string to CheckAbonSuccessResponseModel. Is it possible or not? I was trying but it shows just amount inside Result element.I need just know how I must write DefaultHandler class.
Thanks in advance.

JAXB check if XML-Tag has specific attribute

I'm working at a Method to filter a collection (FileList) of xml-files if a specific xml-tag has an attribute...
In detail... I want to filter all xml-files where the xml-tag has an attribute "is_special", but I've problems to setup my model-classes for the attribute.
At the end I want to store the name of the file and a list of its items, where the value has the attribute is_special="true"
Also I'm using the JAXB Framework with the Moxy extension...
The XML-Structure as followed:
<document>
<id>75C8866AB078DCE541256D16002CF636</id>
<size>806220</size>
<author>xxx</author>
<last_modified>2017.06.12 07:15:41 GMT</last_modified>
<added_to_file>2016.07.05 09:50:44 GMT</added_to_file>
<created>2003.04.28 08:11:06 GMT</created>
<items>
<item>
<name>someName/name>
<type>LNITEMTYPE_DATETIMES</type>
<values>
<value is_special="true"/>
</values>
<last_modified>2003.04.28 08:11:10 GMT</last_modified>
...
</item>
<item>
<name>someName/name>
<type>LNITEMTYPE_TEXT</type>
<values>
<value>SOMETEXT</value>
<value>SOMETEXT</value>
</values>
<last_modified>2003.04.28 08:11:10 GMT</last_modified>
...
</item>
</items>
Therefor I've got 3 Classes for the XML-File...
"XMLDocument.java" implements the list of "Items.java" which implements the list of "Value.java"
XMLDocument.java
#XmlRootElement(name = "notes_document")
public class XMLDocument {
...
private List<Item> items;
...
#XmlElementWrapper(name = "items")
#XmlElement(name = "item")
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
item.java
#XmlRootElement(name = "items")
public class Item {
private String name;
private List<String> values;
private boolean valueIsSpecial;
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElementWrapper(name = "values")
#XmlElement(name = "value")
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
#XmlPath("value/#is_special")
public boolean getValueIsSpecial() {
return valueIsSpecial;
}
public void setValueIsSpecial(boolean valueIsSpecial) {
this.valueIsSpecial = valueIsSpecial;
}
}
value.java
#XmlRootElement(name = "values")
public class Value {
#XmlElement(name = "value")
private String itemValue;
#XmlPath("value/#is_special")
private boolean isSpecial;
public String getValue() {
return itemValue;
}
public void setValue(String value) {
this.itemValue = value;
}
public boolean getValueIsSpecial() {
return isSpecial;
}
public void setValueIsSpecial(boolean isSpecial) {
this.isSpecial = isSpecial;
}
}
My Method so far...
public void FilterTree_isSpecial() throws JAXBException, FileNotFoundException {
for(String file: FileList) {
if (file.endsWith(".xml") && !file.contains("databaseinfo.xml")) {
JAXBContext context = JAXBContext.newInstance(NotesDocumentMetaFile.class);
Unmarshaller um = context.createUnmarshaller();
NotesDocumentMetaFile docMetaFile = (XMLDocument) um.unmarshal(new FileReader(file));
for (int i = 0; i < docMetaFile.getItems().size(); i++) {
// CHECK IF THE <value> OF THIS ITEM HAS ATTRIBUTE is_special
}
}
}
}
Much text... I hope anyone can give me a solution :/
Actually the xpath in your Item.java needs to be : values/value/#is_special like #XmlPath("values/value/#is_special")
If you want the is_special in your Value.java also your xpath should be :
#is_special like : #XmlPath(#is_special)
Also your Item.java, Value.java needs a little change. You don't need #XmlRootElement, you already had it in your XmlDocument.java
Your Item.java should be :
public class Item
{
private String name;
private String type;
private String lastModified;
private List<Value> values;
private String isSpecial;
#XmlPath("values/value/#is_special")
public String getIsSpecial() {
return isSpecial;
}
public void setIsSpecial(String isSpecial) {
this.isSpecial = isSpecial;
}
#XmlElement(name="type")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#XmlElement(name="last_modified")
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
#XmlElement(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElementWrapper(name="values")
#XmlElement(name="value")
public List<Value> getValues() {
return values;
}
public void setValues(List<Value> values) {
this.values = values;
}
}
Your Value.java should be :
public class Value
{
#XmlPath("text()")
private String value;
#XmlPath("#is_special")
private String isSpecial;
public String getIsSpecial() {
return isSpecial;
}
public void setIsSpecial(String isSpecial) {
this.isSpecial = isSpecial;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Note that to get value and is_special in Value.java, you could use #XmlPath.
Now you can call getIsSpecial() on Item.java to check if it is special.

JAXB unmarshalling works on Java 1.8 but returns null values in Java 1.7

I need my server to unmarshal xml files. I have implemented the class to do this on my own computer running Java 1.8 and it works perfectly. However when I run the exact same code on the server, which runs Java 1.7, the object is created but I get a null value for the 'domain' element.
My code may not be ideal practice when using JAXB, but as I said on java 1.8 it does exactly what I need it to. Does anybody have an idea as to the cause of this behaviour? Any help would be greatly appreciated.
This is an example xml file which I am trying to unmarshal:
<planning:metadata xmlns:planning="http://planning.com">
<domain id=numeric">
<title xml:lang="en">The numeric formulation</title>
<files_last_modified>2002-06-01T12:00:00</files_last_modified>
<metadata_last_modified>2014-04-02T11:31:17.471631</metadata_last_modified>
<published>2002-06-01T12:00:00</published>
<link>http://ipc.icaps.org/</link>
<requirements>
<typing/>
<fluents/>
</requirements>
<problems>
<problem domain_file="domain.pddl" number="1" problem_file="p01.pddl"/>
<problem domain_file="domain.pddl" number="2" problem_file="p02.pddl"/>
<problem domain_file="domain.pddl" number="3" problem_file="p03.pddl"/>
<problem domain_file="domain.pddl" number="4" problem_file="p04.pddl"/>
<problem domain_file="domain.pddl" number="5" problem_file="p05.pddl"/>
<problem domain_file="domain.pddl" number="6" problem_file="p06.pddl"/>
</problems>
</domain>
</planning:metadata>
This is the java file:
package server;
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.Date;
#XmlRootElement(name="metadata")
public class XmlDomain {
private XmlDomain.Domain domain;
public XmlDomain.Domain getDomain() {
return domain;
}
#XmlElement
public void setDomain(XmlDomain.Domain domain) {
this.domain = domain;
}
public static class Domain {
private String id;
private String title;
private Date filesModifiedDate;
private Date metaModifiedDate;
private Date publishedDate;
private String link;
private Requirements requirements;
private Problems problems;
public String getId() {
return id;
}
#XmlAttribute
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
#XmlElement
public void setTitle(String title) {
this.title = title;
}
public Date getFiles_last_modified() {
return filesModifiedDate;
}
#XmlElement
public void setFiles_last_modified(Date date) {
filesModifiedDate = date;
}
public Date getMetadata_last_modified() {
return metaModifiedDate;
}
#XmlElement
public void setMetadata_last_modified(Date date) {
metaModifiedDate = date;
}
public Date getPublished() {
return publishedDate;
}
#XmlElement
public void setPublished(Date date) {
publishedDate = date;
}
public String getLink() {
return link;
}
#XmlElement
public void setLink(String link) {
this.link = link;
}
public Requirements getRequirements() {
return requirements;
}
#XmlElement
public void setRequirements(Requirements requirements) {
this.requirements = requirements;
}
public Problems getProblems() {
return problems;
}
#XmlElement
public void setProblems(Problems problems) {
this.problems = problems;
}
public static class Requirements {
// Strings representing domain requirements
private String strips = null;
private String typing = null;
private String durative = null; // durative-actions
private String fluents = null;
private String timed = null; // time-initial-literal
private String equality = null;
private String inequalities = null; // duration_inequalities
public String getStrips() {
return strips;
}
#XmlElement(name = "strips")
public void setStrips(String strips) {
this.strips = strips;
}
public String getTyping() {
return typing;
}
#XmlElement(name = "typing")
public void setTyping(String typing) {
this.typing = typing;
}
public String getDurative() {
return durative;
}
#XmlElement(name = "durative-actions")
public void setDurative(String durative) {
this.durative = durative;
}
public String getFluents() {
return fluents;
}
#XmlElement(name = "fluents")
public void setFluents(String fluents) {
this.fluents = fluents;
}
public String getTimed() {
return timed;
}
#XmlElement(name = "timed-initial-literals")
public void setTimed(String timed) {
this.timed = timed;
}
public String getEquality() {
return equality;
}
#XmlElement(name = "equality")
public void setEquality(String equality) {
this.equality = equality;
}
public String getInequalities() {
return inequalities;
}
#XmlElement(name = "duration_inequalities")
public void setInequalities(String inequalities) {
this.inequalities = inequalities;
}
}
public static class Problems {
private ArrayList<Problem> problems;
public ArrayList<Problem> getProblem() {
return problems;
}
public void setProblem(ArrayList<Problem> problems) {
this.problems = problems;
}
public static class Problem {
private String domainFile;
private int number;
private String problemFile;
public String getDomain_file() {
return domainFile;
}
#XmlAttribute(name = "domain_file")
public void setDomain_file(String domainFile) {
this.domainFile = domainFile;
}
public int getNumber() {
return number;
}
#XmlAttribute
public void setNumber(int number) {
this.number = number;
}
public String getProblem_file() {
return problemFile;
}
#XmlAttribute(name = "problem_file")
public void setProblem_file(String problemFile) {
this.problemFile = problemFile;
}
public void addResult(Planner planner, double result) {
resultMap.put(planner, result);
}
public double getResult(Planner planner) {
return resultMap.get(planner);
}
public HashMap<Planner, Double> getResultMap() {
return resultMap;
}
}
}
}
}
And the package file:
#XmlSchema(
namespace = "http://planning.com",
elementFormDefault = XmlNsForm.QUALIFIED)
package server;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Your XML is incorrect according to your schema as defined by your java objects. Everything in your schema is under the http://planning.com namespace but in your XML the only element defined in that namespace is metadata. You need either:
Set http://planning.com to the default namespace.
<metadata xmlns="http://planning.com">
<domain id=numeric">
...
Use the prefix on all the elements
<planning:metadata xmlns:planning="http://planning.com">
<planning:domain id=numeric">
...
Alternativly if the XML can be assumed to be correct but your Java classes are incorrect. In this case just remove the #XmlSchema annotation from your package-info.java and make your Java read:
#XmlRootElement(name="metadata", namespace="http://planning.com")
public class XmlDomain {
...
You dont really have a question in your post as a commentered mentioned so I am unsure if your asking why this works in 1.8 and not in 1.7 and are aware that the XML is incorrect or just didnt know you have some bad XML.
As to why this works in 1.8 is still a mystery to me. I will do a little bit more poking at it and try to find out why out of my own curiosity.

Json mapping with JaxB annotation using Jackson

How to serialize this class using Jackson
package com.progressivebeef.service.response;
#XmlRootElement(name = "response")
#XmlSeeAlso({ User.class, Profile.class,MenuItem.class,Feedlot.class,Document.class,FeedlotDocument.class })
public final class PBResponse {
private Integer status = FAILURE;
private String code;
private String message;
private Integer totalRecords;
private List<Model> list = new ArrayList<Model>();
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
#XmlElementWrapper(name = "PBBeans")
#XmlAnyElement
public List<Model> getList() {
return list;
}
public void setList(List<Model> list) {
this.list = list;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Integer getTotalRecords() {
return totalRecords;
}
public void setTotalRecords(Integer totalRecords) {
this.totalRecords = totalRecords;
}
/**
* #author tiqbal
* Resets the response.
*/
public void reset(){
this.status = FAILURE;
this.list = new ArrayList<Model>();
this.code = null;
this.message = null;
this.totalRecords = null;
}
}
Jackson is not picking up #XmlElementWrapper #XmlSeeAlso annotations, also Jackson is not mapping #XmlRootElement annotation. I am using Jackson 1.9.0. Jackson is putting elements in the list but not mapping root element of POJO classes.
Here is sample method.
package com.progressivebeef.service.impl;
#Service("/ActivityServiceImpl/")
#Path("/activityservice/")
public class ActivityServiceImpl implements ActivityService {
#POST
#Produces(MediaType.APPLICATION_JSON)
#Override
public Response inputJson(User user ) {
System.out.println("user ");
user.setUser_name("check user name");
Profile profile = new Profile();
profile.setFirst_name("abc");
profile.setLast_name("khan");
user.setProfile( profile );
PBResponse response = new PBResponse();
response.getList().add(user);
return Response.ok(response).build();
}
}
The response it generating is '{"response":{"status":0,"PBBeans":[{"user_name":"check user name","password":"click123","user_role_key":2,"profile":{"first_name":"abc","last_name":"khan","tableName":"pb_profile","pk":"profile_id"},"tableName":"pb_user","pk":"user_id"}]}}'
not picking up the bean's root name inside PBBeans tag.
Hope this helps. Basically, you need to set the WRAP_ROOT_VALUE to true in your mapper.

Categories

Resources