XStream Alias of List root elements - java

I want to be able to alias the root list element depending upon what type of objects are contained in the list. For example, this is my current output:
<list>
<coin>Gold</coin>
<coin>Silver</coin>
<coin>Bronze</coin>
</list>
And this is what I want it to look like:
<coins>
<coin>Gold</coin>
<coin>Silver</coin>
<coin>Bronze</coin>
</coins>
I can do this at a global level by saying all lists should be aliased to coins, but I have a lot of different lists and this won't work. Any ideas on how to do this? Seems like it should be simple, but of course, it isn't.
EDIT: I should specify, I am trying to serialize objects to xml. I am using Spring 3 MVC as my web framework.

Let's say you have a Coin class with a type attribute, as follows:
#XStreamAlias("coin")
public class Coin {
String type;
}
And you have a Coins class that constains a List of Coin:
#XStreamAlias("coins")
public class Coins{
#XStreamImplicit
List<Coin> coins = new ArrayList<Coin>();
}
Pay attention to the annotations. The List is Implicit and the Coins class will be shown as "coins".
The output will be:
<coins>
<coin>
<type>Gold</type>
</coin>
<coin>
<type>Silver</type>
</coin>
<coin>
<type>Bronze</type>
</coin>
</coins>
It's not the same you asked for, but there is a reason.
At first, coin have only one attribute, but we are not sure if all objects you want to show do have only one attribute too. So, we need to tell which object attribute we are talking about.
You can also show the Coin attributes as XML Attributes, not fields. As follows:
#XStreamAlias("coin")
public class Coin {
#XStreamAsAttribute
String type;
Coin(String type) {
this.type = type;
}
}
Here is the output:
<coins>
<coin type="Gold"/>
<coin type="Silver"/>
<coin type="Bronze"/>
</coins>
Hope it helps.

This isn't an ideal solution, as it requires a separate wrapper class, but you could do something like this:
public class CoinResponse {
private List<Coin> coinList;
public CoinResponse(List<Coin> coinList) {
this.coinList = coinList;
}
public List<Coin> getCoins() {
return this.coinList;
}
}
And here's the ugly part:
List<Coin> coins = Arrays.asList( new Coin(), new Coin(), new Coin());
CoinResponse response = new CoinResponse(coins);
XStream xstream = new XStream();
xstream.alias( "coins", CoinResponse.class );
xstream.addImplicitCollection( CoinResponse.class, "coinList" );
System.out.println(xstream.toXML(response));
Basically, this is telling Xstream to use "coins" when converting the CoinResponse, and then don't use any name at all for the list itself.

#XStreamAlias("coins")
public class Coins {
#XStreamImplicit(itemFieldName="coin")
List<String> coins = new ArrayList<String>();
}

Related

Java: creating several instances of object in class itself or how to restructure

I'm a java beginner and have a question concerning how to best structure a cooking program.
I have a class called Ingredient, this class currently looks like this:
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor,String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
I want to initialize several objects (about 40) with certain values as instance variables and save them in a Map, for example
Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)");
Later on I want to retrieve all these objects in the form of a Map/HashMap in a different class.
I'm not sure how to proceed best, initialize all these objects in the Ingredient class itself or provide a method that initializes it or would it be better to create an super class (AllIngredients or something like that?) that has a Map with Ingredients as instance variables?
Happy for any suggestions, thanks in advance :)
Please do not initialize all these objects in the Ingredient class itself. That would be a bad practice for oops.
Just think your class is a template from which you create copies(objects) with different values for attributes. In real world if your class represent model for a toy plane which you would use to create multiple toy planes but each bearing different name and color then think how such a system would be designed. You will have a model(class). Then a system(another class) for getting required color and name from different selection of colors and names present(like in database,files,property file ) etc.
Regarding your situation .
If predetermined values store the values in a text file,properties file,database,constants in class etc depending on the sensitivity of the data.
Create Ingredient class with constructors
Create a class which will have methods to initialize Ingredient class using predetermined values,update the values if required,save the values to text file -database etc and in your case return as map .
Also check the links below
http://www.tutorialspoint.com/design_pattern/data_access_object_pattern.htm
http://www.oracle.com/technetwork/java/dataaccessobject-138824.html
Sounds to me like you are looking for a static Map.
public class Ingredient {
private String identifier;
private double ingredientFactor;
private String titleInterface;
public Ingredient(String identifier, double ingredientFactor, String titleInterface) {
this.identifier = identifier;
this.ingredientFactor = ingredientFactor;
this.titleInterface = titleInterface;
}
static Map<String, Ingredient> allIngredients = new HashMap<String, Ingredient>();
static {
// Build my main set.
allIngredients.put("Almonds (ground)", new Ingredient("Almonds (ground)", 0.7185, "Almonds (ground)"));
}
}

Accessing a list in a Java object

I have been trying to figure this for 1hr30 now and its too confusing for what seems like a really simple problem so I came here to ask.
I send a get request to a 3rd party API to get anime (movie) details as xml.
I store these in a class Ann.java that was automatically generated by netbean's JAXB xml bindings from a sample xml response.
Originally the xml file I used returned only a single anime entry so I could use
String output = gt.fetchMovie().getAnime().getName();
Where gt is my web service. This would print the name of the anime to my IDE.
I changed the setup so that the 3rd party API response gives me multiple anime results instead of just one. I now search for "evangelion" and get 3 results.
However, the new schema of the xml and java class means that attributes are stored as lists. E.g. if I want to access an anime's getName it is within this structure:
public class Ann {
protected List<Object> animeOrManga;
public List<Object> getAnimeOrManga() {
if (animeOrManga == null) {
animeOrManga = new ArrayList<Object>();
}
return this.animeOrManga;
}
public String getName() {
return name;
}
I have been trying to figure out how to return getName but can't find anything that explains what I want to do. I'm not smart enough to just "figure this out" and have been 1hr30 trial and error already.
I know I want to do something like this but guessing the syntax is impossible and everything just goes red, or cannot find symbol, or whatever.
List<Object> = gt.fetchMovie().getAnimeOrManga();
For each (list object)
getName();
Thankyou for reading!
how about create a class that has name attribute like
public class Animal {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
then you can use with
List<Animal> animeOrManga = gt.fetchMovie().getAnimeOrManga();
then you can use with each.
The pseudocodish you provided can be written in Java as follows:
List<Ann> list = new ArrayList<Ann> // You want the list as specific as possible
list.clone(gt.getAnimeOrManga());
for(Ann listObject : list) { // For each loop
listObject.getName();
}
What is used is a for-each loop, which is exactly what is sounds: for each thing in this list do this.
The clone() method takes an arraylist and copies it into the new one.
See here: How do I copy the contents of one ArrayList into another?

Serialization of non-primitives using Jackson

I am trying to serialize a JSON object using Jackson and save into a mysql database using hibernate. All fields of my POJO class are able to be serialized except for any field that isn't a primitive.
public class Teacher {
private Set<Student> students;
private int id;
// getters and setters
}
In this case it would fail on students, creating an infinite recursive loop through the reference chain. I can stop it with #JsonIgnoreProperty but I want this field to be serialized. I am serializing my object like so:
ObjectMapper mapper = new ObjectMapper();
Teacher myTeacher = new Teacher();
mapper.writeValueAsString(teacher);
The only workaround I can think of is appending a string to the end of teacher while still ignoring the property but I am not sure if I will be able to read students as a JsonNode from the tree if I do this.
A way around this would be to use a pure Array or an ArrayList which are serialized fine with Jackson.
For example, I can serialize a class with all these parameters :
public class Map{
private short [][] someMapType;
private short [][] someOtherMap;
private ArrayList<Mill> someMills, otherMills;
private ArrayList<OtherPOJO> myPOJOList;
private String action = "myDefaultAction";
...
}
Where Mill and OtherPOJO are class with not much more than a couple of arrays and other primitives : pure POJOs.
It works fine both ways with Jackson and MongoJack (jackson serializer for MongoDb).
If you can't get away from the set than you have to understand properly what is the fundamental data structure in a set. This should help but you are probably already aware of that.
A way to work around this structure limitation would be to create non-dumb getters and setters. The main disadvantage behind this method is that you run one more for loop over all your elements every time you serialize or de-serialize. This might slightly reduce performance.
The getter is fairly simple :
public Student[] getStudents(){
return this.students.toArray();
}
And the setter is also pretty trivial :
public void setStudents(Student[] students){
this.students = new Set<Student>(); // Or anything that builds the right Set for you
for(int i = 0; i < students.length; i++){
this.students.add(students[i]);
}
}
I wrote it quickly, let me know if there is any bug.
I hope it helps!
Found a decent workaround:
#JsonIgnore
public Set<Student> getStudents() {
return students;
}
#JsonProperty("Students")
public String getStudentsForJson() {
String[] studentNames = new String[this.students.size()];
int i = 0;
for(Student student : this.students) {
studentNames[i] = student.getName();
i++;
}
return StringUtils.join(studentNames, ", ");
}
This saves all student names as one string which I'm able to easily serialize and deserialize as a field.

java best data structure for two to many relations

So I have three important factors, filenames which there are many, there will also be duplicates, violation types which there are 6 of, and the data relating to them.
I was thinking of using a Map for this but it only accepts two types, so I want to sort the data by the filename and for every entry under that filename, i want to retrieve the violation type, from what i want it to retrieve all the matches from the data, so say it's a map I could of said map.get(filename, violation) and it will retrieve all the results that match that.
Is there a data structure that can allow me to do this? or am I being lazy and should just sort the data myself when it comes to outputting it.
One other way to approach this would be to use a custom Class for holding the needed data. Essentially 'building' your own node that you can iterate over.
For example! you could create the following class object: (Node.java)
import java.util.*;
public class Node
{
private String violationType;
private String dataInside;
public Node()
{
this("", "");
}
public Node(String violationType)
{
this(violationType, "");
}
public Node(String violationType, String dataInside)
{
this.violationType = violationType;
this.dataInside = dataInside;
}
public void setViolationType(String violationType)
{
this.violationType = violationType;
}
public void setDataInside(String dataInside)
{
this.dataInside = dataInside;
}
public String getViolationType()
{
return violationType;
}
public String getDataInside()
{
return dataInside;
}
}
ok, great, so we have this 'node' thing with some setters, some getters, and some constructors for ease of use. Cool. Now lets see how to use it:
import java.util.*;
public class main{
public static void main(String[] args){
Map<String, Node> customMap = new HashMap<String, Node>();
customMap.put("MyFilename", new Node("Violation 1", "Some Data"));
System.out.println("This is a test of the custom Node: " + customMap.get("MyFilename").getViolationType());
}
}
Now we have a map that relates all of the data you need it to. Now, you'll get a lot of people saying 'Don't reinvent the wheel" when it comes to things like this, because built in libraries are far more optimized. That is true! If you can find a data structure that is built into java that suits your needs, USE IT. That's always a good policy to follow. That being said, if you have a pretty custom situation, sometimes it calls for a custom approach. Don't be afraid to make your own objects like this, it's easy to do in Java, and it could save you a lot of time and headache!
EDIT
So, after re-reading the OP's question, I realize you want an entire list of associated data for the given violation of a given filename. In which case, you would switch the private String dataInside to something like private ArrayList<String> dataInside; which would allow you to associate as much data as you wanted, still inside that node, just inside of an arraylist. Also note, you'd have to switch up the getters/setters a little to accomodate a list, but that's not too bad.
You could use a custom class for a mapkey which contains the two fields filename and violation type. When doing so you need to implement equals() and hashCode() methods do ensure instances of that class can be used as key for map.
You can use TreeMap. TreeMap is sorted according to the natural ordering of its keys.
TreeMap<String, List<String>> map = new TreeMap<String, List<String>>();

Deserialization of generic collections with Gson

I have some difficulties with json deserialization using GSon and I hope somebody can help me.
I want to deserialize the following json snippet:
{
"fieldA": "valueA",
"myCollection": {
"AnotherClass": [
{
"objectAfieldA": "valueB",
"objectAfieldB": "valueC"
},
{
"objectAfieldA": "valueD",
"objectAfieldB": "valueE"
}
]
}
}
the corresponding overall class has following fields:
...
String fieldA;
List<AnotherClass> = new ArrayList<AnotherClass>();
....
Now, my problem is that when I deserialize, using fromJson(jsonSample, resultContainer.class), without the List<T> element, everything is good, but I get a NullPointerException when I include the contained list. I've read about how to deal with collections of generic types and the use of TypeToken, but I can't apply this knowledge when my collection is part of another class…
I really would appreciate any help to solve this.
The solution for deserealizing the unnamed JSON array is quite simple:
List<resultContainer> lres = gson.fromJson(new FileReader("input.json"), new TypeToken<List<resultContainer>>(){}.getType());
When deserializing, you only need to use the TypeToken if the outer-most structure to be deserialized into is a generic collection. This is not the case for the example in the original question. So, use of a TypeToken is unnecessary.
The issue appears to be that the JSON structure does not match the Java structure attempting to be bound to.
The JSON structure defines
an object with two elements
element 1 is a string named "fieldA",
element 2 is an object named "myCollection", which has one element
the one element is an array named "AnotherClass", composed of objects with two elements
element 1 is a string named "objectAfieldA",
element 2 is a string named "objectAfieldB"
So, define a Java data structure to match that, and deserialization will work very simply, without any custom processing necessary. If such a matching Java structure is not provided, then custom deserialization is necessary.
Here is such a working example using the names and types from the original question.
import java.io.FileReader;
import com.google.gson.Gson;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
resultContainer result = gson.fromJson(new FileReader("input.json"), resultContainer.class);
System.out.println(gson.toJson(result));
}
}
class resultContainer
{
String fieldA;
MyCollectionContainer myCollection;
}
class MyCollectionContainer
{
SomeOtherClass[] AnotherClass;
}
class SomeOtherClass
{
String objectAfieldA;
String objectAfieldB;
}

Categories

Resources