Is it accepted behaviour that MessagePack official implementation in Java serializes public fields as Arrays?
In what universe is this "like JSON"?
My case:
I have a simple class like so:
#Message
public class MySuperClass(){
public int mySuperID; // let's say 4
public byte[] mySuperData; // let's say nothing
public String mySuperType; // let's say null
public String mySuperExtra; // let's say HI!
public MySuperClass(){}
// other constructors
}
And i'm simply serializing with
MessagePack msgpack = new MessagePack();
msgpack.write(mySuperInstance);
And sending that to a distant server written in NodeJS.
Node JS can easily unpack it, to
['HI!', �, 4, null]
Which means that MessagePack is nothing like JSON, because it parses Java objects as arrays and then only repopulates them alphabetically!
Does anyone have a solution that does not include mapping every object I have? (Also HashMap is not unpackable by Node, which means that messagePack is not cross-platform ,thus, repeating, noting like JSON)
Judging from my MessagePack experience, it usually treats objects as MessagePack maps.
It doesn't use any language specific constructs so it is cross - platform.
I think you may be having issues because of the library you are using. You should consider the official one. You can read more about it here. It is basically an extension for Jackson that let's serialise and deserialise Java objects directly to / from MessagePack and was working (at least when I had to use it).
Related
Sometimes, we need to create some thrift objects in unit tests. We can do it by manually create object using Java code, like:
MyObj myObj = new MyObj();
myObj.setName("???");
myObj.setAge(111);
But which is not convenient. I'm looking for a way to create objects with some readable text.
We can convert thrift objects to JSON with TSimpleJSONProtocol, and get very readable JSON string, like:
{ "name": "???", "age": 111 }
But the problem is TSimpleJSONProtocol is write only, thrift can't read it back to construct an instance of MyObj.
Although there is a TJSONProtocol which supports to serialize and deserialize, but the generated JSON is not readable, it uses a very simplified JSON format and most of the field names are missing. Not convenient to construct it in tests.
Is there any way to convert thrift objects to readable string and also can convert it back? If TSimpleJSONProtocol supports converting back, which is just what I'm looking for
The main goal of Thrift is to provide efficient serialization and RPC mechanisms. What you want is something that is - at least partially - contrary to that. Human-readable data structures and machine processing efficiency are to a good extent conflicting goals, and Thrift favors the latter over the former.
You already found out about the TSimpleJson and TJson protocols and about their pros and cons, so there is not much to add. The only thing that is left to say is this: the protocol/transport stack of Thrift is simple enough.
This simplicity makes it possible to add another protocol based on your specific needs without much or overly complicated work. One could probably even write an XML protocol (if anyone really wants such bloatware) in short time.
The only caveat, especially vis-à-vis your specific case, is the fact that Thrift needs the field ID to deserialize the data. So you either need to store them in the data, or you need some other mechanism which is able to retrieve that field ID based on the field and structure names.
I want a method that can convert an object (with a few parameters String or int) in a String, and more importantly, convert that String back in an object. Do you know any way to develop a converter for this purpose?
The problem is that the object is a DTO used by other developpers so I can't modify the toString() method. Thus I created my own method toString, but I don't know how can I reliably make a converter working both ways. I thought about several solutions (storing the objects in a map, etc), but they all seem unclear to read/understand. Is there any usual way to do it that every experienced programmers would understand in a blink of an eye what it does?
EDIT: Well, I know serialization, but my question wasn't clear, I'm sorry. The fact is that I want to display the objects in a ListView (JavaFX), to make them readable, like String "N°:xxxx; Version : 1", serialized objects aren't really esthetic nor readable.
So my final solution is something more like:
listView.setCellFactory(new Callback<ListView<ProductDto>, ListCell<ProductDto>>() {
#Override
public ListCell<ProductDto> call(final ListView<ProductDto> productDtoListView) {
return new ListCell<ProductDto>(){
#Override
protected void updateItem(final ProductDto productDto, final boolean b) {
if(productDto!=null){
setText(fromProductDtoToString(productDto));
}
}
};
}
});
This way, I store the objects themselves in the ListView, and can still display a fairly esthetic String representing the object.
Thanks for your time.
Fabien
You can for example use Jackson to convert object to JSON and vice versa. Check this article How To Convert Java Object To / From JSON
If you want, you can use XML binding too.
In general, there are number of serialization libraries/approaches:
XStream (for XML but not for JSON)
Jackson (for JSON)
Jackson xml module (faster than XStream)
Kryo (a fast, compact binary serialization format)
Smile (a binary format that comes with Jackson 1.6 and later).
Java Object Serialization.
SimpleXML seems solid, runs at 2x the speed of XStream, but requires more configuration effort
YamlBeans
SnakeYAML
Jackson JSON, Kryo, and Jackson Smile are all significantly faster than good old Java Object Serialization, by about 3x to 4.5x. XStream is on the slow side.
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.
I'm trying to flatten an object graph completely to a map.
Complex objects should also be flattened to the top level using "namespaces". So if the object A contains an int i, a string pid and another object B that contains a string id, the resulting Map would look like {i=1, pid="test", B.id="test1"}.
I also want to be able to reconstruct the original object from a given map.
I've searched around for libraries that do this. But I'm not quite getting what I'm looking for. I see stuff that maintains the hierarchy but nothing that completely flattens the structure.
I do see something in Spring Integration that looks like what I want to do:
http://static.springsource.org/spring-integration/api/org/springframework/integration/transformer/ObjectToMapTransformer.html#ObjectToMapTransformer%28%29
But I can't get it to work.
Any help would be appreciated.
Thanks.
The Apache BeanUtils library has a describe() method that does something similar to what I was looking for.
Another possible solution would be via the Jackson JSON library, since JSON objects are essentially key-value pairs.
Related discussions: How to convert a Java object (bean) to key-value pairs (and vice versa)?
Have you considered using Protobufs?
The json-flattener library solves exactly your problem
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.)