Deserializing XML in Android using X-Stream - java

SOLVED
Changed Contents contents to:
// Lists
#XStreamImplicit(itemFieldName = "Contents")
public List<Contents> Contents = new ArrayList<Contents>();
I'm trying to deserialize the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
<type>Test</type>
<uid>1</uid>
<depends>1</depends>
<catid>1</catid>
<label>Test</label>
<defaultVal>default</defaultVal>
<answer>Test</answer>
<Contents>
<Content>
<uid>1</uid>
<label>Test</label>
</Content>
</Contents>
</Item>
</Items>
The problem is that when I reach Contents it crashes due to going deeper by another level.
This is how i DeSerialize my XML, it works without the contents.
public static Object DeSerializeFromXML(String xml, Class items, Class item)
{
XStream xstream = new XStream();
xstream.processAnnotations(new Class[] { items, item });
return xstream.fromXML(xml);
}
Here's how I call the DeSerialize method:
Items reader = (Items)Data.Serialization.Instance().DeSerializeFromXML(xml, Items.class, Item.class);
And as last my Objects:
Items.cs
#XStreamAlias("Items")
public class Items
{
public Items() { items = new ArrayList<Item>(); }
#XStreamImplicit(itemFieldName = "Item")
public List<Item> items = new ArrayList<Item>();
}
Item.cs
#XStreamAlias("Item")
public class Item
{
// Type
public String type = "";
// Ids
public int uid = 0;
public int catid = 0;
public int depends = 0;
// Values
public String label = "";
public String defaultVal = "";
public String answer = "";
// Lists
public Contents content;
public Item()
{
}
public Item(String type, int uid, int catid, int depends, String label,
String defaultval, String answer)
{
this.type = type;
this.uid = uid;
this.catid = catid;
this.depends = depends;
this.label = label;
this.defaultVal = defaultval;
this.answer = answer;
content = new Contents();
}
#XStreamAlias("Contents")
public static class Contents
{
public Contents()
{
contents = new ArrayList<Content>();
}
#XStreamImplicit(itemFieldName = "Content")
public List<Content> contents = new ArrayList<Content>();
}
Content.cs
#XStreamAlias("Content")
public class Content
{
public int uid = 0;
public String label = "";
public Content()
{
}
public Content(int uid, String label)
{
this.uid = uid;
this.label = label;
}
I'm not quite sure if my annotations for the next level are correct.
Any help is appreciated.

Solved it by changing Contents to a list and adding the XStream marshall to it.
#XStreamImplicit(itemFieldName = "Contents")
public List<Contents> Contents = new ArrayList<Contents>();

Related

How to go through a Gson object, with multiple levels Arrays

I'm trying to get the parameters inside jSon items>item>image>images>transparent using the Gson library. The idea is to capture transparent, transparent_blank and transparent_dark. But I don't know how I can get these values, for the moment I have created the following:
Json
{
"date_layout":"day-month-year",
"lastupdate":1547596830,
"items":[{
"name":"Cleans Cuts",
"featured":"true",
"item":{
"image":"http:www.domain.com/unwanted_image.jpg",
"images":{
"transparent":"http:www.domain.com/desired_image1.jpg",
"transparent_blank":"http:www.domain.com/desired_image2.jpg",
"transparent_dark":"http:www.domain.com/desired_image3.jpg"
}
}
},
{
"name":"Cleans Cuts",
"featured":"true",
"item":{
"image":"http:www.domain.com/unwanted_image.jpg",
"images":{
"transparent":"http:www.domain.com/desired_image1.jpg",
"transparent_blank":"http:www.domain.com/desired_image2.jpg",
"transparent_dark":"http:www.domain.com/desired_image3.jpg"
}
}
}]
}
.MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String url = "http://www.example.com/file.json";
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
if(response.isSuccessful()){
String response_jSon = response.body().string();
Gson gson = new Gson();
Datos datosFinal = gson.fromJson(response_jSon, Datos.class);
for (int i=0; i<datosFinal.items.size(); i++){
Log.d("msg_2", datosFinal.items.get(i).name);
}
}
And I'm only able to get to items as you can see in the .MainActivity Log.
Class Objects for the Json
Datos.java
public class Datos {
public String date_layout;
public Int lastupdate;
List<items> items;
}
items.java
public class items {
public String name;
}
The json is not very clean, I would suggest that you rework how this json string is generated, but if you still want to achieve getting those values without reworking the json, you need to change your Items class to :
`public class items {
public String name;
public String featured;
public Item item;
}`
Then you need to create another class called Item
`public class Item{
public String image;
public Image images;
}`
You will also need to create an Image class, like so:
`public class Image {
public String transparent;
public String transparent_blank;
public String transparent_dark;
}`
Then you can log these values in your loop:
`Datos datosFinal = gson.fromJson(response_jSon, Datos.class);
for (int i=0; i<datosFinal.items.size(); i++){
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent);
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent_blank);
Log.d("msg_2", datosFinal.items.get(i).item.images.transparent_dark);
}`
While this may work, I would highly suggest you to rework your json and make it easier to maintain.
You have to create the following class also to getting value for transparent, transparent_blank and transparent_dark
Images.java
Item.java
Replace this class:
public class Items{
private Item item;
private String name;
private String featured;
public Item getItem ()
{
return item;
}
public void setItem (Item item)
{
this.item = item;
}
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
public String getFeatured ()
{
return featured;
}
public void setFeatured (String featured)
{
this.featured = featured;
}
}
Add this class:
public class Images{
private String transparent_blank;
private String transparent_dark;
private String transparent;
public String getTransparent_blank ()
{
return transparent_blank;
}
public void setTransparent_blank (String transparent_blank)
{
this.transparent_blank = transparent_blank;
}
public String getTransparent_dark ()
{
return transparent_dark;
}
public void setTransparent_dark (String transparent_dark)
{
this.transparent_dark = transparent_dark;
}
public String getTransparent ()
{
return transparent;
}
public void setTransparent (String transparent)
{
this.transparent = transparent;
}
}
Also, Add this Class:
public class Item {
private Images images;
private String image;
public Images getImages ()
{
return images;
}
public void setImages (Images images)
{
this.images = images;
}
public String getImage ()
{
return image;
}
public void setImage (String image)
{
this.image = image;
}
}
Now, you will get the value using the getter method.
you must use
public class items {
public String name;
#Expose(serialize = false, deserialize = false)
public String featured;
#Expose(serialize = false, deserialize = false)
public item mItem;
}
public class item {
#Expose(serialize = false, deserialize = false)
public String image;
#Expose(serialize = false, deserialize = false)
public images mImages;
}
public class images {
#Expose(serialize = false, deserialize = false)
public String transparent;
#Expose(serialize = false, deserialize = false)
public String transparent_blank;
#Expose(serialize = false, deserialize = false)
public String transparent_dark;
}
you can genetate pojo by using http://www.jsonschema2pojo.org/

How to create a pojo from xml for jaxb ( Unmarshalling)

<?xml version="1.0" encoding="UTF-8"?>
<STATUS_UPDATE>
<UPDATES_COUNTER>2</UPDATES_COUNTER>
<LETTERS>
<LETTER>
<LETTER_KEY>key1</LETTER_KEY>
<STATUS>status1</STATUS>
</LETTER>
<LETTER>
<LETTER_KEY>key2</LETTER_KEY>
<STATUS>status2</STATUS>
</LETTER>
</LETTERS>
</STATUS_UPDATE>
So i have this xml. Im trying to create a pojo from it.
#XmlRootElement(name = "STATUS_UPDATE")
public class StatusUpdate {
private int updatesCounter;
List<Letter> letters;
public StatusUpdate(){
letters = new ArrayList<Letter>();
}
public StatusUpdate(int updatesCounter, List<Letter> letters){
super();
this.updatesCounter = updatesCounter;
this.letters = letters;
}
#XmlElement(name="LETTERS")
public List<Letter> getLetters() {
return letters;
}
public void setLetters(List<Letter> letters) {
this.letters = letters;
}
#XmlElement(name="UPDATES_COUNTER")
public int getUpdatesCounter() {
return updatesCounter;
}
public void setUpdatesCounter(int updatesCounter) {
this.updatesCounter = updatesCounter;
}
}
And letter class
#XmlRootElement(name = "LETTER")
public class Letter {
public Letter(){
}
public Letter(String letterKey,String status){
this.letterKey = letterKey;
this.status = status;
}
String letterKey;
String status;
#XmlElement(name="LETTER_KEY")
public String getLetterKey() {
return letterKey;
}
public void setLetterKey(String letterKey) {
this.letterKey = letterKey;
}
#XmlElement(name="STATUS")
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
and this code snipper wont seem to do the job.
i get no errors, code runs, i get a 2 in my updateCounter variable,
but my list is empty with only one letter object, with both variables null.
File file = new File("myFile.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(StatusUpdate.class );
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StatusUpdate msgObject = (StatusUpdate) jaxbUnmarshaller.unmarshal(file);
I've been reading the documentations and examples, but most of them are either written to match variable names and xml elemenets (which i dont want to) or are either not helpfull to me.
Any ideas? I have a feeling i'm very close to my goal but i can't seem to grasp what i'm missing.
You need to add #XmlElementWrapper(name = "LETTERS") annotation to getLetters() method like this
#XmlElementWrapper(name = "LETTERS")
#XmlElement(name = "LETTER")
public List<Letter> getLetters() {
return letters;
}

Error accessing variable of a nested class

I desperately need help. I have two classes.
One is a PatientRecord with nested classes in it.
The other is a PatientGenerator which fills a database with PatientRecords by generating random data
for each field of the PatientRecord.
My problem is that I can't access the variables of some of the nested classes but I can access others. (At least it compiles for some and fails with an error for others.)
error: cannot find symbol
temp.fname = getRFirstName();
symbol: variable fname
location: variable temp of type PatientRecord.Visitor
Here is the failing calls
private ArrayList<PatientRecord.Visitor> generateVisitors(PatientRecord p) {
int payments = rnd.nextInt(10);
ArrayList<PatientRecord.Visitor> array = new ArrayList<PatientRecord.Visitor>();
for (int i = 0; i < payments; i++) {
PatientRecord.Visitor temp = p.new Visitor();
temp.fname = getRFirstName();
temp.lname = getRLastName();
temp.relation = relations[rnd.nextInt(relations.length)];
array.add(temp);
}
return array;
}
and here is part of the class with nested class Visitor in it.
public class PatientRecord implements Serializable{
public int pId;
public String FirstName;
public String MiddleName;
public String LastName;
public boolean gender;
public Location location;
public ArrayList visitors;
public ArrayList emergencyContacts;
public DateTime discharge;
public Admission admission;
public String primaryDoctor;
public ArrayList procedures;
public ArrayList prescriptions;
public ArrayList nurseNotes;
public ArrayList doctorNotes;
public InsurancePolicy insurancePolicy;
public ArrayList billing; // Arraylist of payments
public PatientRecord() {
init();
}
public PatientRecord(int id) {
pId = id;
init();
}
private void init() {
visitors = new ArrayList<Visitor>();
emergencyContacts = new ArrayList<Contact>();
location = new Location();
discharge = new DateTime();
admission = new Admission();
procedures = new ArrayList<Procedure>();
prescriptions = new ArrayList<Prescription>();
nurseNotes = new ArrayList<Note>();
doctorNotes = new ArrayList<Note>();
billing = new ArrayList<Payment>();
insurancePolicy = new InsurancePolicy();
}
public class Visitor {
public String fname;
public String lname;
public String relation;
public Visitor() {
}
}
I have no compilation errors (after having removed some of the code):
public class PatientRecord
{
public int pId;
public String FirstName;
public String MiddleName;
public String LastName;
public boolean gender;
public ArrayList visitors;
public ArrayList emergencyContacts;
public String primaryDoctor;
public ArrayList procedures;
public ArrayList prescriptions;
public ArrayList nurseNotes;
public ArrayList doctorNotes;
public ArrayList billing; // Arraylist of payments
public PatientRecord() {
init();
}
public PatientRecord(int id) {
pId = id;
init();
}
private void init() {
visitors = new ArrayList<Visitor>();
}
public class Visitor
{
public String fname;
public String lname;
public String relation;
}
public class PatientGenerator
{
public ArrayList<PatientRecord.Visitor> generateVisitors(PatientRecord p) {
//int payments = rnd.nextInt(10);
ArrayList<PatientRecord.Visitor> array = new ArrayList<PatientRecord.Visitor>();
for (int i = 0; i < 10; i++) {
PatientRecord.Visitor temp = p.new Visitor();
temp.fname = "first";
temp.lname = "last";
temp.relation = "brother";
array.add(temp);
}
return array;
}
}
public static void main(String[] args)
{
PatientRecord t = new PatientRecord();
PatientGenerator c = t.new PatientGenerator();
c.generateVisitors(t);
}
}
Does your code look similar to this?

How to check if an array in an arraylist contains a certain value?

I have an array list which contains arrays of type String. I create the array list and add arrays to it with the following code:
List<String[]> transaction = new ArrayList<String[]>();
String[] transactionLine = new String[7];
transactionLine[0] = "0";
transactionLine[1] = "1";
//.....
transactionLine[6] = "some value";
transactionLines.add(transactionLine);
Now I want to test if one of the arrays contain a certain value. I tried it like this, but then it checks for an array and not an element of an array:
if(transactionLines.contains("some value")) {
//Do some stuff with it
}
I know this doesn't work, but I don't now how to do it otherwise. I couldn't find any post of this already on Stackoverflow (not with the logical search terms for this problem anyway).
Note: I have chosen this structure of arrays in an arraylist, because I have a fixed number of columns (as suggested in how to create dynamic two dimensional array in java?).
Any help is greatly appreciated!
#assylias suggestion to use the object oriented way is good, but his example does not tell if the list contains a transaction where one property has a certain value. This example does:
public class Test {
public static void main(final String[] args) {
final List<TransactionLine> transaction = new ArrayList<>();
transaction.add(new TransactionLine(1, "some value"));
transaction.add(new TransactionLine(2, "another value"));
transaction.add(new TransactionLine(3, "yet another value"));
System.out.println(containsName(transaction, "some value"));
System.out.println(containsName(transaction, "non-existent value"));
}
// Iterates over all transactions until a transaction is found that has the
// same name as specified in search
private static boolean containsName(final List<TransactionLine> transaction, final String search) {
for (final TransactionLine transactionLine : transaction) {
if (transactionLine.getName().equals(search)) {
return true;
}
}
return false;
}
private static class TransactionLine {
private int id;
private String name;
public TransactionLine(final int id, final String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
}
Here is an example with two classes (Transaction and TransactionLine):
Test:
public class Test {
public static void main(final String[] args) throws Exception {
final Transaction transaction = new Transaction();
transaction.add("some name");
transaction.add("another name");
transaction.add("yet another name");
System.out.println(transaction.containsName("some name"));
System.out.println(transaction.containsName("non-existent name"));
}
}
Transaction:
import java.util.ArrayList;
import java.util.List;
public class Transaction {
private final List<TransactionLine> transactionLines = new ArrayList<>();
public void add(final String name) {
final TransactionLine tl = new TransactionLine(transactionLines.size(), name);
transactionLines.add(tl);
}
public boolean containsName(final String name) {
for (final TransactionLine transactionLine : transactionLines) {
if (transactionLine.getName().equals(name)) {
return true;
}
}
return false;
}
}
TransactionLine:
public class TransactionLine {
private int id;
private String name;
public TransactionLine() {
}
public TransactionLine(final int id, final String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
}
The object oriented way of solving your problem would be to create a class:
class Transaction {
private final int id;
private final String name;
//etc.
}
Then if you need to test if a given transaction is in the list you could implement equals and hashcode in that class, which would enable you to call:
if(transactionLines.contains(someTransaction)) { ... }
If you just need to find transactions with a specific characteristics, you would need to iterate over the list and check each transaction, for example:
Transaction result = null;
for (Transaction t : transacionLines) {
if(t.getName().equals("some value") {
result = t;
break;
}
}
public static boolean isListOfStringArraysContainsString(List<String[]> arrayList, String s) {
for (String[] arr : arrayList) {
for (String string : arr) {
if ((string != null) && (string.equals(s))) {
return true;
}
}
}
return false;
}
Provided code do exactly what you are asking about, but solution provided by #assylias is proper
I got your point. By using ArrayList you are trying to make an array of another array of strings. But you have made one simple mistake.This is how you tried to retrieved a String inside an array inside an ArrayList:
if(transactionLines.contains("some value")) {
//Do some stuff with it
}
This "some value" is a string present in String array "transactionLine" and not referred by the List "transactionLines" (which is referring to ArrayList object).
Instead this is what you should have done:
List<String[]> transactionLines = new ArrayList<String[]>();
String[] transactionLine = new String[7];
transactionLine[0] = "0";
transactionLine[1] = "1";
transactionLine[2] = "something";
transactionLine[3] = "3";
transactionLine[4] = "4";
transactionLines.add(transactionLine);
String[] mySL=transactionLines.get(0);
System.out.println(mySL[2]);
if (mySL[2].equals("something")) {
//some code
} else {
//some code
}
Hope this helps.

Jaxb Arraylist Outputstream

My Xml Should look like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<results>
<version>1.0</version>
<status>ok</status>
<lastUpdate>2011-11-21 09:23:59.0</lastUpdate>
<total>2</total>
<row>
<areaId></areaId>
<nameEng></nameEng>
<nameGer></nameGer>
</row>
… more <row></row> blocks …
</results>
How can i achieve this..?
At the moment i have the following.. but i dont know how i can return the album2 to the outputstream as a String...
List<Row> rows = new ArrayList<Row>();
while(rs.next()){
int albumId = rs.getInt(1);
int bookDocId = rs.getInt(2);
String picUrl = rs.getString(3);
String descEng = rs.getString(4);
String descGer = rs.getString(5);
Row row = new Row();
row.setAlbumId(albumId);
row.setBookDocId(bookDocId);
row.setPicUrl(picUrl);
row.setDescEng(descEng);
row.setDescGer(descGer);
rows.add(row);
}
Album album = new Album();
album.setRows(rows);
File file = new File("album.xml");
JAXB.marshal(album, file);
Album album2 = JAXB.unmarshal(file, Album.class);
file.deleteOnExit();
EDIT:
#XmlRootElement
public class Album {
private List<Row> rows = new ArrayList<Row>();
#XmlElement(name="row")
public List<Row> getRows(){
return this.rows;
}
public void setRows(List<Row> rows){
this.rows = rows;
}
Row.class:
public class Row {
private int albumId;
private int bookDocId;
private String picUrl;
private String descEng;
private String descGer;
public int getAlbumId() {
return albumId;
}
public int getBookDocId() {
return bookDocId;
}
public String getPicUrl() {
return picUrl;
}
public String getDescEng() {
return descEng;
}
public String getDescGer() {
return descGer;
}
public void setAlbumId(int albumId) {
this.albumId = albumId;
}
public void setBookDocId(int bookDocId) {
this.bookDocId = bookDocId;
}
public void setPicUrl(String picUrl) {
this.picUrl = picUrl;
}
public void setDescEng(String descEng) {
this.descEng = descEng;
}
public void setDescGer(String descGer) {
this.descGer = descGer;
}
}
}
This is my code, it works well
#javax.xml.bind.annotation.XmlType
#javax.xml.bind.annotation.XmlAccessorType(javax.xml.bind.annotation.XmlAccessType.FIELD)
public class Album
{
long version;
String status;
java.util.List<Row> rows;
}
#javax.xml.bind.annotation.XmlType
#javax.xml.bind.annotation.XmlAccessorType(javax.xml.bind.annotation.XmlAccessType.FIELD)
public class Row
{
String areaId;
String nameEng;
String nameGer;
}
Test
public static void main(final String[] args) throws IOException
{
Album al = new Album();
List<Row> rows = new ArrayList<Row>();
final Row row1 = new Row();
row1.areaId = "area1";
row1.nameEng = "eng1";
row1.nameGer = "ger1";
final Row row2 = new Row();
row2.areaId = "area2";
row2.nameEng = "eng2";
row2.nameGer = "ger2";
rows.add(row2);
rows.add(row1);
al.status = "stat";
al.rows = rows;
final File file = new File("D:/test.xml");
final FileOutputStream out = new FileOutputStream(file);
JAXB.marshal(al, out);
final Album after = JAXB.unmarshal(file, Album.class);
assert after.status.equals(al.status);
assert after.rows.size() == al.rows.size();
}
You can change access to private and add getters, setters
To return like String use
ByteArrayOutputStream output = new ByteArrayOutputStream();
JAXB.marshal(al, output);
output.toString();
If you're asking how to write an Album to an output stream rather than write it to a file, then the answer is simple: JAXB.marshal(Object, OutputStream).
If you're asking how to transform an Album into an XML string, then the answer is also simple: JAXB.marshal(Object, String).
If you're asking something else, please clarify your question.

Categories

Resources