How can I serialize and deserialize JavaBeans without using JSON, Protobuf, Java serialization API, and other serializations? I have to implement this interface instead:
interface Encode
{
byte[] serialize(Object anyBean);
Object deserialize(byte[] byteArray);
}
How can this be done?
You can implement your own solution but the existing APIs available are providing really good solutions, why bypassing them?
Related
I am struggling to find a library that will serialise a simple graph of Java objects to/from JSON (no need for circular refs or anything). I don't want to have Java class names in the output but including an extra "#type": "foo" property is fine. It must work with untyped collections and maps. I expect to have to do something like mapper.registerType(MyClass.class, "foo") to specify the type mappings but the library must take it from there. Anyone know of such a thing?
Jackson should be able to handle what it is that you are trying to do. Check out the examples from this link, most specifically #4 for polymorphic type deserialization
Jackson
Polymorphic Type Handling
Examples
Take a look at Genson it provides full databinding support, with polymorphic and untyped objects and has many other features.
// this defines aliases for classes, if you don't care of class names being
// serialized then just enabled type ser/deser using builder.setWithClassMetadata(true)
Genson genson = new Genson.Builder()
.addAlias("person", Person.class)
.addAlias("other", Some.class)
.create();
// serialize using with type information
String json = genson.serialize(object);
// deserializing to an unkown type based on the type information in the json string
genson.deserialize(json, Object.class);
Do you search something like this?
http://code.google.com/p/json-io/
json-io consists of two main classes, a reader (JsonReader) and a
writer (JsonWriter). There is a 3rd rigorous test class
(TestJsonReaderWriter). json-io eliminates the need for using
ObjectInputStream / ObjectOutputStream to serialize Java and instead
uses the JSON format.
...
Usage
json-io can be used directly on JSON Strings or with Java's Streams.
Basically, I want to have an interface for converting Objects to/from their XML or JSON String representation, something like
public interface IStringifier{
/**
Converts the Object to it's String representation, e.g. XML or JSON
*/
public String toString(Object o);
/**
Converts from the String representation (e.g. XML or JSON) to an Object
*/
public Object fromString(String s, Class<?> clazz);
}
Such an interface would be fairly simple to implement in GSON, XStream etc. but by abstracting it you are abstracted from knowing just what is going on underneath. And you are decoupled from one of the many many XML or JSON libraries, so clients are freer to pick their favorite.
Is there any "standard" Java interface for this? Something in Guava, Apache, etc?
(added) None of the answers were what I really wanted ("yes, in javax.obscure.interfaces there's what you want") but thanks for the replies. I'll accept Tom's answer as the most informative/provocative. And maybe I'll clean up the code I have and try to create a standard. :-)
JAXB (JSR-222) is the Java SE/EE standard for converting objects to/from XML. It can be used standalone and is the standard binding layer for JAX-WS (SOAP) and JAX-RS (RESTful) Web Services. Below is a link to an example of specifying an alternate provider via a jaxb.properties file.
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
There currently isn't a standard API for JSON binding.
I think you're overthinking this. You don't actually care about turning objects into Strings, you want to be able to serialize objects to different formats without knowing what that format is. But who says that different format is a String? What happens when you want your object to be available as a protocol buffer? That's a binary format, not a character format -- so stringify() won't help there. Ultimately, it's up to you to architect your application to be as independent as possible of those details.
XML and JSON are unrelated, so this is actually two questions:
For JSON, although "unofficial", a popular library is GSON.
For XML, see Blaise's answer
One popular JSON-to-Java binding library is Jackson
One popular XML-to-Java binding library is XStream
If you intend to use this in a web application, maybe you would like to consider Spring 3 MVC's facilities for this. Through annotations it does the conversion automatically and you can tell it whether you want XML or JSON (or various other formats). This might be the common interface you are looking for too.
We've gotten a .NET project and want to serialize and deserialize JSON in .NET, Java and Objective-C. Unfortunately, we've got the following situation: one attribute in the data model maps to 4 other classes that all inherit from the same base class. Hence, when receiving the not-stereotyped JSON format, we don't know which type to serialize one of these 4 objects to.
As a solution, we want to integrate a "type"-attribute, telling the serializer which class to serialize the object to. JSON.NET actually supports this: http://json.codeplex.com/discussions/56031
We're now looking for experiences of other developers with serializers/deserializers on the Java and Objective-C platform. Is there any chance to modify these serializers in a way that it reacts on the type-attribute?
Gson for java support it too. I have same problem and solve it with custom serializer/deserialized. All you have to do: implements your serializer/deserializer and register it in GsonBuilder. Read about it here.
I was going through a blog and one question came to my head. Is it possible to overwrite the way ObjectOutputStream is writing.
Let's say i am writing to a file out.dat i.e.
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File("C:\\out.dat")));
out.writeObject(o);
When i opened the file out.dat in Notepad++, i saw the binary data. Which makes sense. What if, I would like to customize the way this data is being written. Lets say i want my out.dat file in JSON format (Thats just an example, It could be any other format). What method should i overwrite to do this?
You'll be able to do what you want by implementing Externalizable and overriding the writeExternal and readExternal methods. See http://download.oracle.com/javase/7/docs/platform/serialization/spec/output.html#3146 for details.
Note that it will allow customizing the output of the serialization of one object, but not the format of the whole stream. You will thus find your JSON string inside other binary data.
i think that you shouldn do it, because this format is used to keep comunication between tiers (work with distributed objects on a network). What you can do is just create a handler that store your object in a file using your pretty format.
You can make your object implement Externalizable and have full control over serialization. Use e.g. google-gson for JSON when implementing the readExternal / writeExternal methods.
In your scenario , where you are looking for a custom serialization mechanism , I would recommend that you implement Externalizable interface and provide implementations of methods
public void writeExternal(ObjectOutput out) throws IOException
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
Its entirely up to you how you want to serialize in this case.
I'm pretty sure that java does not have internal support for serializing to JSON. In my opinion your best bet is to create a interface for a getting the JSON and have any objects you want serialized to JSON implement this interface:
public interface IJSONSerializable{
public String getSerializedForm();
}
And then use a basic FileOutputStream to output since (as I understand it) the ObjectOutputStream is used to serialize a object to binary and does not have inherent support for JSON.
Other Thoughts
If you choose to go this way you could write a helper class for writing out things such as a property and a value.
Well Java itself has no built-in support for JSON serialization, but then I'm sure you can find frameworks that do that - or just write it yourself for simple classes.
So for any class you want to serialize in JSON format just overwrite
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
Shouldn't be too hard if there's some JSON framework out there that gives you the data of one instance in string format and vice versa.
How can I implement serialization on my own. Meaning I don't want my class to implement serializable. But I want to implement serialization myself. So that without implementing serializable I can transfer objects over network or write them to a file and later retrieve them in same state. I want to do it since I want to learn and explore things.
Serialization is the process of translating the structure of an object into another format that could be easily transfered across network or could be stored in a file. Java serializes objects into a binary format. This is not necessary if bandwidth/disk-space is not a problem. You can simply encode your objects as XML:
// Code is for illustration purpose only, I haven't compiled it!!!
public class Person {
private String name;
private int age;
// ...
public String serializeToXml() {
StringBuilder xml = new StringBuilder();
xml.append("<person>");
xml.append("<attribute name=\"age\" type=\"int\">").append(age);
xml.append("</attribute>");
xml.append("<attribute name=\"name\" type=\"string\">").append(name);
xml.append("</attribute>");
xml.append("</person>");
return xml.toString();
}
Now you can get an object's XML representation and "serialize" it to a file or a network connection. A program written in any language that can parse XML can "deserialize" this object into its own data structure.
If you need a more compact representation, you can think of binary encoding:
// A naive binary serializer.
public byte[] serializeToBytes() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
// Object name and number of attributes.
// Write the 4 byte length of the string and the string itself to
// the ByteArrayOutputStream.
writeString("Person", bytes);
bytes.write(2); // number of attributes;
// Serialize age
writeString("age", bytes);
bytes.write(1); // type = 1 (i.e, int)
writeString(Integer.toString(age), bytes);
// serialize name
writeString("name", bytes);
bytes.write(2); // type = 2 (i.e, string)
writeString(name, bytes);
return bytes.toByteArray();
}
private static void writeString(String s, ByteArrayOutputStream bytes) {
bytes.write(s.length());
bytes.write(s.toBytes());
}
To learn about a more compact binary serialization scheme, see the Java implementation of Google Protocol Buffers.
You can use Externalizable and implement your own serialization mechanism. One of the difficult aspects of serialization is versioning so this can be a challenging exercise to implement. You can also look at protobuf and Avro as binary serialization formats.
You start with reflection. Get the object's class and declared fields of its class and all superclasses. Then obtain value of each field and write it to dump.
When deserializing, just reverse the process: get class name from your serialized form, instantiate an object and set its fields accordingly to the dump.
That's the simplistic approach if you just want to learn. There's many issues that can come up if you want to do it "for real":
Versioning. What if one end of the application is running new version, but the other end has an older class definition with some fields missing or renamed?
Overwriting default behavior. What if some object is more complex and cannot be recreated on a simple field-by-field basis?
Recreating dependencies between objects, including cyclic ones.
... and probably many more.
Get the Java Source code and understand how Serialization is implemented. I did this some month ago, and now have a Serialization that uses only 16% of the space and 20% of the time of "normal" serialization, at the cost of assuming that the classes that wrote the serialized data have not changed. I use this for client-server serialization where I can use this assumption.
As a supplement to #Konrad Garus' answer. There is one issue that is a show-stopper for a full reimplementation of Java serialization.
When you deserialize an object, you need to use one of the object's class's constructors to recreate an instance. But which constructor should you use? If there is a no-args constructor, you could conceivably use that. However, the no-args constructor (or indeed any constructor) might do something with the object in addition to creating it. For example, it might send a notification to something else that a new instance has been created ... passing the instance that isn't yet completely deserialized.
In fact, it is really difficult replicate what standard Java deserialization code does. What it does is this:
It determines the class to be created.
Create an instance of the class without calling any of its constructors.
It uses reflection to fill in the instance's fields, including private fields, with objects and values reconstructed from the serialization.
The problem is that step 2. involves some "black magic" that a normal Java class is not permitted to do.
(If you want to understand the gory details, read the serialization spec and take a look at the implementation in the OpenJDK codebase.)