Convert String to my desired object - java

I have a list of Attachment type [Attachment is a class which contains some getters and setters].But due to some reasons I need to convert this list to string and after that I have to fetch this list from string.
public class Attachment{
private Integer attachmentCode;
private String attachmentDesc;
}
Attachment attach1 = new Attachment();
Attachment attach2 = new Attachment();
List<Attachment> tempList = new ArrayList<>();
tempList.add(attach1);
tempList.add(attach2);
HibernateClass record = new HibernateClass();
record.setValue(tempList .toString());
If I want to fetch Attachment object from this String value, how can I achieve my values from this list?

There are several approaches I guess. Using XML or JSON or any other textual format would also be a valid approach.
What about using object serialization and Base64 like follows:
import java.io.*;
import java.nio.charset.*;
import java.util.*;
public class Serialization {
public static void main(String[] args) throws Exception {
Attachment attach1 = new Attachment();
Attachment attach2 = new Attachment();
List<Attachment> tempList = new ArrayList<>();
tempList.add(attach1);
tempList.add(attach2);
String value = serialize(tempList);
List<Attachment> attachments = deserialize(value);
}
private static List<Attachment> deserialize(String value) throws Exception {
byte[] decode = Base64.getDecoder().decode(value);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(decode));
return (List<Attachment>) ois.readObject();
}
private static String serialize(List<Attachment> tempList) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(baos);
os.writeObject(tempList);
byte[] encode = Base64.getEncoder().encode(baos.toByteArray());
return new String(encode, Charset.defaultCharset());
}
private static class Attachment implements Serializable {
private Integer attachmentCode;
private String attachmentDesc;
}
}

Related

How to make BufferedInputStream Serializable?

I need to make java BufferedInputStream Serializable. Are there any alternatives or any other way to implement it?
Do yo see any issue in this implementation
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.Serializable;
public class SerializableBufferedInputStream extends BufferedInputStream implements Serializable
{
public SerializableBufferedInputStream(InputStream in)
{
super(in);
}
public SerializableBufferedInputStream(InputStream in, int size)
{
super(in, size);
}
}
First of all, BufferedInputStream Creates a BufferedInputStream and saves its argument, the input stream in, for later use.
but you are saying Serializable which means converting the state of an object into a byte stream
so why do you need to convert it ??
This thing may help you check (Provide your Code in case you want other than this)
public class MainClass {
public static void main(String[] args) throws Exception {
Punk obj1 = new Punk("A");
Punk obj2 = new Punk("B");
Punk obj3 = new Punk("V");
ObjectOutputStream objectOut = new ObjectOutputStream(new BufferedOutputStream(
new FileOutputStream("C:/punkObjects.bin")));
objectOut.writeObject(obj1); // Write object
objectOut.writeObject(obj2); // Write object
objectOut.writeObject(obj3); // Write object
objectOut.close(); // Close the output stream
ObjectInputStream objectIn = null;
int objectCount = 0;
punk object = null;
objectIn = new ObjectInputStream(new BufferedInputStream(new FileInputStream(
"C:/punkObjects.bin")));
// Read from the stream until we hit the end
while (objectCount < 3) {
object = (punk) objectIn.readObject();
objectCount++;
System.out.println(object);
}
objectIn.close();
}
}
class Punk implements Serializable {
String str;
public Punk(String s) {
str = s;
}
}

Gson JSON max size

I need to extract some data from a Clob and serialize it in JSON format.
What's the maximum size Gson can handle?
Here https://github.com/google/gson/blob/master/UserGuide.md I can just find
"Strings: Deserialized strings of over 25MB without any problems"
Context: I use..
ResultSet.getClob()
-> BufferedReader
-> String singleLine
-> StringBuilder
-> String "jsonAttribute" to serialize
More in detail:
try{
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader( resultset.getClob(2).getCharacterStream() );
String line;
try{
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
}catch(IOException ee){
// logger
throw ee;
}
String jsonAttribute = sb.toString();
}catch(Exception xx){..}
Note: in my current code the limitation is Integer.MAX_VALUE
My solution will consit in using chunks of the data retrieved from the DB. I would like to know the theoretical max size that GSON can handle. I won't use a browser on the receiving side.
Gson doesn't impose any limit. Nor it has any known arquitectural limitation.
I think the main problem you will face with your approach is loading the data into memory in the first place.
I recommend using Gson stream API to write the JSON as you read it from the database. Use a JsonWriter and create and stream your JSON object.
Reader reader = resultset.getClob(2).getCharacterStream();
JsonWriter jsonWriter = new JsonWriter(someOutputStream);
copyStream(reader, someOutputStream);
Where copyStream could be something like
public static void copyStream(Reader istream, Writer ostream) throws IOException {
char buffer[] = new char[2048];
while (true) {
int len = istream.read(buffer);
if (len == -1)
return;
ostream.write(buffer, 0, len);
}
}
I confirm #sargue answer. I tried the following test and worked like a charm with the right amount of heap memory allocated to the jvm.
#Test
public void testGsonLimitss(){
EntityHalConverter<HugeData> converter = new EntityHalConverter<>(HugeData.class);
HugeData hugeData = new HugeData();
converter.toJson( hugeData );
}
class HugeData implements HalResource {
String big1, big2;
public HugeData(){
// big1 = StringUtils.repeat("X", 400000000); // 300 millions chars ~ approx 3 mb. With multibyte chars ..... 3.5 mb
big2 = StringUtils.repeat("Y", Integer.MAX_VALUE-10);
}
}
This is the converter I'm using (with Halarious) ..
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import ch.halarious.core.HalResource;
import ch.halarious.core.HalSerializer;
import ch.halarious.core.HalDeserializer;
import ch.halarious.core.HalExclusionStrategy;
public class EntityHalConverter <T> {
private Gson gson;
private GsonBuilder builder;
private Class<T> paramType;
/* HalConverter<ProgrammeData> halConverter = new HalConverter<>(ProgrammeData.class);
*/
public EntityHalConverter(Class<T> paramType) {
builder = new GsonBuilder();
builder.setExclusionStrategies(new HalExclusionStrategy());
this.paramType = paramType;
}
/* String jsonResult = halConverter.toJson( programmeData );
*/
public String toJson( T result ) throws JsonParseException{
builder.registerTypeAdapter(HalResource.class, new HalSerializer());
gson = builder.create();
return gson.toJson(result, HalResource.class);
}
/* ProgrammeData pcsProg = halConverter.convert( jsonString );
*/
public T fromJson( String json ) throws JsonParseException {
builder.registerTypeAdapter( HalResource.class, new HalDeserializer(paramType) );
gson = builder.create();
return (T)gson.fromJson( json, HalResource.class );
}
}

Make JsonNode Serializable

This seems to be simple but I failed to get a serialized JsonNode deserialized. Here is my test class
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Foo implements Serializable {
private String string;
private transient JsonNode jsonNode;
public Foo(String string, JsonNode jsonNode) {
this.string = string;
this.jsonNode = jsonNode;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
if (this.jsonNode != null) out.writeObject((new ObjectMapper()).writeValueAsBytes(this.jsonNode));
// out.writeObject(this.jsonNode.textValue());
}
private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException {
in.defaultReadObject();
this.jsonNode = (new ObjectMapper()).readValue(in, JsonNode.class);
}
}
When I tried to deserialize I got this error
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
Here is the unit test
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.testng.annotations.Test;
import java.io.*;
import static org.testng.Assert.assertEquals;
public class FooTest {
#Test
public void testSerialization() {
JsonNodeFactory nodeFactory = new JsonNodeFactory(false);
ObjectNode node = nodeFactory.objectNode();
ObjectNode child = nodeFactory.objectNode(); // the child
child.put("message", "test");
node.put("notification", child);
Foo foo = new Foo("Bar", node);
String fileName = "foo.ser";
try (
OutputStream file = new FileOutputStream(fileName);
OutputStream buffer = new BufferedOutputStream(file);
ObjectOutput output = new ObjectOutputStream(buffer);
){
output.writeObject(foo);
}
catch(IOException ex){
ex.getStackTrace();
}
Foo fooNew = null;
//deserialize the ser file
try(
InputStream file = new FileInputStream(fileName);
InputStream buffer = new BufferedInputStream(file);
ObjectInput input = new ObjectInputStream (buffer);
){
//deserialize the Object
fooNew = (Foo) input.readObject();
}
catch(ClassNotFoundException ex){
ex.printStackTrace();
}
catch(IOException ex){
ex.printStackTrace();
}
assertEquals(foo, fooNew);
}
}
Your read and write operations are not matched.
On the write side you use ObjectOutputStream.writeObject(Object) to write a byte[] containing the serialized JSON content. On the read side you try to read raw bytes off the stream with ObjectMapper.readValue(InputStream, Class) when you actually need to read a byte[] object first as that is what you wrote and then use ObjectMapper.readValue(byte[], Class).
Alternatively and probably a better solution is you could use ObjectMapper.writeValue(OutputStream, Object) instead on the write side.
Try this:
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
if(jsonNode == null){
out.writeBoolean(false);
} else {
out.writeBoolean(true);
new ObjectMapper().configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false).writeValue(out, jsonNode);
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
if(in.readBoolean()){
this.jsonNode = new ObjectMapper().configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false).readValue(in, JsonNode.class);
}
}

Android parse Plist file

Hello Im trying to parse an plist file that contains array of dict's. Im trying to do this using xmlwise. The content of the plistfile is here
So far I only have this in my activity and im getting the content of the plistfile, but how to parse the content into an arraylist?
Map<String, Object> properties = null;
try {
InputStream inputStream = getResources().openRawResource(R.raw.first_5);
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
properties = Plist.fromXml(sb.toString());
// TODO do something with the object here
Log.v("--", properties.values() + " " + properties.size());
Log.v("--", "OB "+properties.get());
} catch (Exception e) {
e.printStackTrace();
} finally {
br.close();
}
}
Quick question. What should be the content of the ArrayList? I was wondering if you are mentioning about a list of Object in you Map<String, Object> properties map then why cant you just get the values from the map as
Map<String, Object> properties = new HashMap<String, Object>();
List<Object> plist = new ArrayList<Object>(properties.values());
Apart from that checking your plist the structure is like a Dict root element and a list of Dicts in it. I assume you need to get this as a list. If so consider using Android PList parser by longevitysoft. This is simple and opensource. Its basically a SAXParser parsing Apple PList.
You can then iterate through this array and get approriate object. In your xml its and array of Dict object, so you could do something like this
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import com.longevitysoft.android.xml.plist.PListXMLHandler;
import com.longevitysoft.android.xml.plist.PListXMLParser;
import com.longevitysoft.android.xml.plist.domain.Array;
import com.longevitysoft.android.xml.plist.domain.Dict;
import com.longevitysoft.android.xml.plist.domain.PList;
import com.longevitysoft.android.xml.plist.domain.PListObject;
public class PlistReader {
public static void main(String[] args) throws Exception {
PListXMLParser parser = new PListXMLParser();
PListXMLHandler handler = new PListXMLHandler();
parser.setHandler(handler);
parser.parse(readFile("plist.xml"));
PList pList = ((PListXMLHandler) parser.getHandler()).getPlist();
Dict root = (Dict) pList.getRootElement();
// This Array class is java.util.ArrayList<PListObject> underneath the
// covers
Array theList = root.getConfigurationArray("Objects");
for (PListObject obj : theList) {
switch (obj.getType()) {
case DICT:
Dict dictionaryObj = (Dict) obj;
// dictionaryObj.getConfigurationObject(key);
// dictionaryObj.getConfigurationInteger(key);
// dictionaryObj.getConfiguration(key);
// dictionaryObj.getConfigurationArray(key)
break;
case STRING:
com.longevitysoft.android.xml.plist.domain.String stringObj = (com.longevitysoft.android.xml.plist.domain.String) obj;
break;
default:
break;
}
}
}
private static String readFile(String path) throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded);
}
}
When i tried parsing your xml i got some exception. That was because the PListXMLHandler was checking for localName and not qualifiedName. This could be easily fixed by checking for localName in startElement() and endElement() methods like.
if(isEmpty(localName)){
localName = qName;
}
Hope this helps.
You can also try Google dd-plist.jar libraries or SAXON parse for parsing plist.
Go through this conversion :
https://code.google.com/p/plist/wiki/Examples
http://developer.android.com/reference/javax/xml/parsers/SAXParser.html
You can use dd-plist jar for doing this, Download dd-plist.jar from Google its nice and fast.
I am putting an example working for me from Google code colud.
Link is here. http://plist.googlecode.com/svn-history/r61/trunk/src/com/dd/plist/XMLPropertyListParser.java
package com.dd.plist.test;
import com.dd.plist.*;
import java.io.File;
import java.util.Arrays;
import java.util.Date;
import junit.framework.TestCase;
public class ParseTest extends TestCase {
/**
* Test the xml reader/writer
*/
public static void testXml() throws Exception {
System.out.println(new File("test-files/"));
// parse an example plist file
NSObject x = PropertyListParser.parse(new File("test-files/test1.plist"));
// check the data in it
NSDictionary d = (NSDictionary)x;
assertTrue(d.count() == 5);
assertTrue(((NSString)d.objectForKey("keyA")).toString().equals("valueA"));
assertTrue(((NSString)d.objectForKey("key&B")).toString().equals("value&B"));
assertTrue(((NSDate)d.objectForKey("date")).getDate().equals(new Date(1322472090000L)));
assertTrue(Arrays.equals(((NSData)d.objectForKey("data")).bytes(),
new byte[]{0x00,0x00,0x00,0x04,0x10,0x41,0x08,0x20,(byte)0x82}));
NSArray a = (NSArray)d.objectForKey("array");
assertTrue(a.count() == 4);
assertTrue(a.objectAtIndex(0).equals(new NSNumber(true)));
assertTrue(a.objectAtIndex(1).equals(new NSNumber(false)));
assertTrue(a.objectAtIndex(2).equals(new NSNumber(87)));
assertTrue(a.objectAtIndex(3).equals(new NSNumber(3.14159)));
// read/write it, make sure we get the same thing
PropertyListParser.saveAsXML(x, new File("test-files/out-testXml.plist"));
NSObject y = PropertyListParser.parse(new File("test-files/out-testXml.plist"));
assertTrue(x.equals(y));
}
/**
* Test the binary reader/writer.
*/
public static void testBinary() throws Exception {
NSObject x = PropertyListParser.parse(new File("test-files/test1.plist"));
// save and load as binary
PropertyListParser.saveAsBinary(x, new File("test-files/out-testBinary.plist"));
NSObject y = PropertyListParser.parse(new File("test-files/out-testBinary.plist"));
assertTrue(x.equals(y));
}
/**
* NSSet only occurs in binary property lists, so we have to test it separately.
*/
public static void testSet() throws Exception {
NSSet s = new NSSet();
s.addObject(new NSNumber(1));
s.addObject(new NSNumber(2));
s.addObject(new NSNumber(3));
PropertyListParser.saveAsBinary(s, new File("test-files/out-testSet.plist"));
NSObject t = PropertyListParser.parse(new File("test-files/out-testSet.plist"));
assertTrue(s.equals(t));
}
public static void testASCII() throws Exception {
NSObject x = PropertyListParser.parse(new File("test-files/test1-ascii.plist"));
NSDictionary d = (NSDictionary)x;
assertTrue(d.count() == 5);
assertTrue(((NSString)d.objectForKey("keyA")).toString().equals("valueA"));
assertTrue(((NSString)d.objectForKey("key&B")).toString().equals("value&B"));
assertTrue(((NSDate)d.objectForKey("date")).getDate().equals(new Date(1322472090000L)));
assertTrue(Arrays.equals(((NSData)d.objectForKey("data")).bytes(),
new byte[]{0x00,0x00,0x00,0x04,0x10,0x41,0x08,0x20,(byte)0x82}));
NSArray a = (NSArray)d.objectForKey("array");
assertTrue(a.count() == 4);
assertTrue(a.objectAtIndex(0).equals(new NSNumber(true)));
assertTrue(a.objectAtIndex(1).equals(new NSNumber(false)));
assertTrue(a.objectAtIndex(2).equals(new NSNumber(87)));
assertTrue(a.objectAtIndex(3).equals(new NSNumber(3.14159)));
NSObject y = PropertyListParser.parse(new File("test-files/test1-ascii-gnustep.plist"));
assertTrue(x.equals(y));
}
public static void testASCIIWriting() throws Exception {
File in = new File("test-files/test1.plist");
File out = new File("test-files/out-test1-ascii.plist");
NSDictionary x = (NSDictionary)PropertyListParser.parse(in);
PropertyListParser.saveAsASCII(x, out);
NSDictionary y = (NSDictionary)PropertyListParser.parse(out);
assertTrue(x.equals(y));
}
public static void testGnuStepASCIIWriting() throws Exception {
File in = new File("test-files/test1.plist");
File out = new File("test-files/out-test1-ascii-gnustep.plist");
NSDictionary x = (NSDictionary)PropertyListParser.parse(in);
PropertyListParser.saveAsGnuStepASCII(x, out);
NSObject y = PropertyListParser.parse(out);
assertTrue(x.equals(y));
}
}

How can I create a Global FileInputStream object, which will be available to access from other class within in my project?

What I wanted to do is create a global FileInputStream object and use it a long of my application.
I have the follow class which create my FileInputStream objec and return the result of my query over the XML file:
package Engine;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import com.ximpleware.AutoPilot;
import com.ximpleware.VTDException;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
public class BACENGQueryXMLbyVTD {
public String query;
public String path;
public BACENGQueryXMLbyVTD(String query, String path) {
this.query = query;
this.path = path;
}
public ArrayList query() throws IOException, VTDException {
System.out.println(path);
File f = new File(path);
//System.out.println(f);
FileInputStream fis = new FileInputStream(f);
//System.out.println(fis);
byte[] xmlContent = new byte[(int) f.length()];
fis.read(xmlContent);
VTDGen vg = new VTDGen();
vg.setDoc(xmlContent);
vg.parse(false);
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
int node = 0;
ap.selectXPath(query);
int i;
ArrayList<String> interfaces = new ArrayList<String>();
while ((i = ap.evalXPath()) != -1) {
vn.push();
interfaces.add(vn.toString(i + 1));
}
ap.resetXPath();
return interfaces;
}
}
This class is called from my main class which has a loop.
for (int c = 0; c < nodeNames.size(); c++) {
String Queries2 = "/import_data/group/node[#name='" +nodeNames.get(c) + "']/interface/#network_value";
BACENGQueryXMLbyVTD getNodesInterfaces = new BACENGQueryXMLbyVTD(Queries2, TransitPath);
listOfNodeInterfaces = getNodesInterfaces.query();
}
It's working fine, however in order to reduce the consume of IO resource over my server HD. I would like to create an unique FileInputStream object and use it for each query whcih has to be executed.
Could somebody point out the way to do it?
Separate your concerns - BACENGQueryXMLbyVTD is both loading the data and executing the query.
First load the file into a byte[] outside your loop, then pass it to BACENGQueryXMLbyVTD. You might also want to pass the query as an argument to the query method.
You'll end up with a BACENGQueryXMLbyVTD that looks like this (with the disclaimer that I'm not familiar with VTD-XML, so this might the creation of objects from that API might not work exactly like this):
public class BACENGQueryXMLbyVTD
{
private byte[] doc;
public BACENGQueryXMLbyVTD(byte[] doc)
{
this.doc = doc;
}
public List<String> query(String query) throws IOException, VTDException
{
VTDGen generator = new VTDGen();
generator.setDoc(doc);
generator.parse(false);
VTDNav navigator = generator.getNav();
AutoPilot autoPilot = new AutoPilot(navigator);
autoPilot.selectXPath(query);
List<String> nodeInterfaces = new ArrayList<String>();
int i;
while ((i = autoPilot.evalXPath()) != -1)
{
navigator.push();
nodeInterfaces.add(navigator.toString(i + 1));
}
return nodeInterfaces;
}
}
That you can then call like:
byte[] xmlContent = ... //load the xml from anywhere you like, not just a file as previously.
BACENGQueryXMLbyVTD getNodesInterfaces = new BACENGQueryXMLbyVTD(xmlContent);
for (String nodeName : nodeNames)
{
String query = "/import_data/group/node[#name='" + nodeName + "']/interface/#network_value";
nodeInterfaces = getNodesInterfaces.query(query);
...
}
You might also want to switch to the standard Java XPATH APIs - they're a lot clearer and better documented than VTD-XML.

Categories