can I converted serialized java objects to text? - java

I have some code for reading and writing objects in Java (using serialization) as well as some objects.
I would like to convert them to text, so someone else, from another platform can use these objects with my code (which is just provided as a package).
I could write a whole parser for text format for the objects. However, there is a deadline coming, and I was hoping it might be much easier to do it some other way, so that person can explore the objects and my Java code himself.
So I guess, my question is: what is the easiest way to migrate from Java serialization to writing objects in convenient ascii form? (though I suspect the answer is: write a parser yourself! :-))

I suggest you to use some standard format, such as YAML or aforementioned JSON or XML. If your objects form a hierarchical structure without circular dependencies, I'd choose JSON and use Jackson JSON processor - is actively developed and easy to use.
If your objects have circular dependencies, I'd choose YAML, because it can handle then using references, so it'll work even if you have complex object structures. SnakeYAML seems to be a good choice.
I was keen to test another library yamlbeans to see how it handles circular dependencies, so I made a small example for myself. Here it is:
// YamlEx.java
import java.io.*;
import java.util.*;
import com.esotericsoftware.yamlbeans.*;
public class YamlEx {
public static void main(String argv[])
throws Exception
{
Person p1 = new Person("John");
Person p2 = new Person("Paul");
Person p3 = new Person("Bob");
// create a circular dependencies, even to self (p1-p1)
p1.setFriends2(p2, p1, p3);
p2.setFriends2(p1);
p3.setFriends2(p1, p2);
// serialize
CharArrayWriter w = new CharArrayWriter();
YamlWriter writer = new YamlWriter(w);
writer.write(p1);
writer.close();
// print it to the console
System.out.println(w.toString());
// read it again
Reader r = new CharArrayReader(w.toCharArray());
YamlReader reader = new YamlReader(r);
p1 = reader.read(Person.class);
reader.close();
System.out.println(String.format("%s's friends: %s",
p1.name, p1.getFriends() ));
}
}
// Person.java
import java.util.*;
public class Person {
// A public field as a test.
public String name;
public Person() {
}
public Person(String name) {
this.name = name;
}
public String toString() {
return name;
}
// A set/get pair as a test.
private List<Person> friends0;
public List<Person> getFriends() {
return friends0;
}
public void setFriends(List<Person> p) {
this.friends0 = p;
}
public void setFriends2(Person... p) {
setFriends(Arrays.asList(p));
}
}
Works as expected:
&1 !Person
name: John
friends: !java.util.Arrays$ArrayList
- &2 !Person
name: Paul
friends: !java.util.Arrays$ArrayList
- *1
- *1
- !Person
name: Bob
friends: !java.util.Arrays$ArrayList
- *1
- *2
John's friends: [Paul, John, Bob]

Using XML seems to be way to go here...
For a certain situation in our project we have used deserialization to XML via Xstream. You can also give it a shot... it's easy.

I'd suggest that your serialized object should be packed into Base64 string, then sent to another platform, decrypted from Base64 and casted to new object, just as described here: How to serialize an object into a string
I've seen many implementations of given problem and Base64 seems to be the easiest way.

I'd go for JSON, much easier and more human readable.
There are lot of JSON libraries for almost all languages. Especially for java i always prefer these two.
GSON
JACKSON
Where JACKSON has some performance advantages.
There is simple guide too.

Related

Is it possible to parse JSON data of one complex object to custom object via API

I have a web project with 2 Java Entities(Lets Say E1,E2) like how mybatis and VO works.
Object structure:
class E1{
String a;
.... n other data members
E2 e2;
}
class E2{
String b;
.... n other data members
}
Is it possible to make a single class in Android project, i.e.
class E1 {
String a;
String b; //This Data member belongs to class E2
}
and parse it with the help of a framework (like Jackson) or I have to write a custom class for that?
My JSON Data will look like this:
{
"E1": {
"a": "some data",
.
.
.
"E2": {
"b": "some data",
.
.
other data
}
}
}
Is there any API which can do this?
I asked this because with my web Application its not just 2 Class but atleast 10 interconnected class and I am not Using them in my android app. So don't wanna replicate the same classes in android app.
Also if you can suggest any other possible way.
It would be a very bad design practice/approach, making things very difficult to debug, error prone and not future proof (think about it, what if you add to one of the 10 classes a field that conflict with another class' field?).
Anyway, if you still want to trick your way out of the correct approach that would be to have 10 classes, I am not aware of any lib that provides you with this feature. You could parse json ==> 10 Java Map, then merge the 10 Map through the Map::putAll method and finally pass the obtained Map that contains all the objects to Jackson.
Your best bet is to use #JsonAnySetter annotation from Jackson library on the receiver POJO.
public class E1{
public String a;
private Map<String, Object> paramMap = new HashMap<>();
#JsonAnyGetter
public Map<String, Object> getParamMap() {
return paramMap;
}
#JsonAnySetter
public void setParamMap(String s, Object o) {
paramMap.put(s, o);
}
}
This will put every unimplemented attributes in a HashMap.
In combination with #JsonAnyGetter, the serialization of the receiver POJO will give the same result as the JSON input.

Create JSON File Serializing the class in Java

I have the following class:
public class PDFValues {
private String value;
private int xPos;
private int yPos;
public PDFValues(){
}
public PDFValues(String value, int x, int y){
this.setValue(value);
this.setX(x);
this.setY(y);
}
public void setValue(String value){
this.value = value;
}
public void setX(int x){
this.xPos = x;
}
public void setY(int y){
this.yPos = y;
}
public String getValue(){
return this.value;
}
public int getX(){
return this.xPos;
}
public int getY(){
return this.yPos;
}
}
And then I want to do this:
public class PDFtoJSONTest {
public static void main(String[] args) {
List<PDFValues> listaElementos = new ArrayList<PDFValues>();
listaElementos.add(new PDFValues("Anubis Lockward Botello",
new Integer(100), new Integer(633)));
....more code
}
}
What I want to do, is save all the PDFValues in the ArrayList, as a JSON file, but I don't know how to make it automatic, I thought of Serializing the object or something, but I can't find a solution to this and I'm not sure how I could make the PDFValues object serializable.
I want to do this to save those values in a JSON file and then use them as properties to generate a PDF file, I'm using PDFBox for the generation of the PDFs files and SimpleJSON for the .json ones.
I'm working on a project where I'd have to generate thousands of pdf files out of some processed data. I've already managed to parse the data which consists of about 500+ MBs of text and holds around five thousand account statements which need to be generated as PDFs.
The thing is, that seeings as the Text data is generated in PDFs, one needs to indicate the position of the starting character in a string to PDFValues, to generate a PDFTextInfo object and then add it to the PDF, the file would need to contain images and text and other stuff.
Note: If there's a better way to accomplish what I'm trying to do, I'm open to suggestions, but I'd also like an answer to what I'm trying to do, and know if it would work or not, and why for both cases.
I'd like to make my code as fast as possible, right now I'm able to process the whole TXT file from RAW to mostly clean data in under 2 minutes and I know it might be optimized but right now that's not the point :D
I'd like to generate the PDFs files as fast as possible, but I've been working with that project in Java for like 1 1/2 months now, and I've only learned about JSON and PDF file generation in the past week...it's been three days of working on the JSON file and I'm a bit lost.
Here's an example of the file output for the JSON file that I'm trying to accomplish, this one I generated it manually and I managed to read and process the file, now I'm trying to generate it automatically:
{
"Header": {
"FullName":
{
"Name":"Anubis Lockward Botello",
"Horizontal":180,
"Vertical":633
},
..... more elements .....
}
}
As you can see, I'm trying to divide the elements on the pdf files as if they were panels, like HEADER, BALANCES, TRANSACTIONS and stuff, and build the PDF file as if they were pieces of a puzzle, but right now I'm trying to "build" the name element on the header.
I would guess there is a better way to do build PDF files than writing and then re-reading a file, but I can provide one answer for your JSON question.
Use the Apache commons-lang3 library and look into ToStringBuilder. You can then define a toString() method on your object and use the built-in ToStringStyle.JSON_STYLE format. You'd then have to wrap your list of PDFValues in some other object that can store a PDFValue for Header, FullName, etc..
#Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append("Name", value)
.append("Horizontal", xPos)
.append("Vertical", yPos)
.toString();
}
I should note that you could pull in Jackson or similar libraries, annotate your objects with the required JsonProperty annotations and use the library to serialize your object to JSON as you would for REST or similar. But, for a simple use case like yours, the ToStringBuilder is simple and effective.
OK, I managed to get this far thanks to JudgingNotJudging, what I did was taking his answer and applying a Decorator Pattern to the object, so that I have a PDFValue, that's inside a PDFElement, that's part of a PDFContainer, so it goes like this:
Header: (this is our PDFContainer)
FullName: (so, Header HAS-A FullName element)
PDFValue: (and FullName HAS-A a PDFValue, that has the Name or value to be shown, and the X and Y coordinates inside the PDF)
Here's the code:
The PDFValue class is still the same, and I added the overridden toString() method according to JudgingNotJudging's answer.
public class PDFValuesDecorator extends PDFValues{
}
In PDFValuesDecorator we don't do anything, we're just going to extend PDFValues so that we have the correct type of the class we want to add behavior to, and still get a common type for all the different classes we might create this way.
public class PDFElement extends PDFValuesDecorator {
private PDFValues pdfValue;
private String elementID;
public PDFElement(PDFValues pdfValue, String elementID){
this.pdfValue = pdfValue;
this.elementID = elementID;
}
#Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append(elementID, pdfValue.toString())
.toString();
}
}
In the constructor we save the instance of the object we're trying to "wrap" so that we can "add" something to it. In this case, we're adding an ID for the element and we're modifying the toString() method of the element to also include the toString() method of the PDFValue, so that they both show both of their values in the appropriate order.
Finally, here's my main method:
public class PDFtoJSONTest {
public static void main(String[] args) {
List<PDFValues> listaElementos = new ArrayList<PDFValues>();
PDFValues name =
new PDFValues(
"Anubis Lockward Botello",
new Integer(100),
new Integer(633)
);
PDFElement fullName = new PDFElement(name, "FullName");
PDFElement header = new PDFElement(fullName, "Header");
listaElementos.add(header);
for(PDFValues value : listaElementos){
System.out.println("Valor: " + value.toJSONString());
}
}
}
As you can see, the first thing I do is create an ArrayList of PDFValues, then I create a single object for the name value, then that name is wrapped inside the FullName element, and then that's stored inside a Header element. As you can see, I can pass around the List object and do with it whatever I want.
And also, I could create other PDFElements like images and stuff, and I can save all of them inside the ArrayList and pass them around and then when I want to save them, I just have to call the toString method once and I would get the correct output, btw, here's the resulting value from the JSON string:
Valor: {"Header":"{"FullName":"{"Name":"Anubis Lockward Botello","Horizontal":100,"Vertical":633}"}"}

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?

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