Map from JSON to java object with different structure - java

I have a JSON string representing an object, and I want to put its information into a Java object B with a different structure. Currently the solution I am taking is creating a Java Object A with a structure identical to the JSON object, made the conversion from JSON to A using Jackson and later, made the mapping from A to B using Dozer with XML mappings. Is there anyway to avoid having the A objects?
Making it short, currently I have this:
JSON--Jackson-->A--Dozer(XML mappings)-->B
and I would like to achieve this
JSON--???-->B

You may know this already, but Jackson can use loosely structure types like Map, or JsonNode as target, so you can do, say:
JsonNode root = mapper.readTree(jsonSource);
Map<String,Object> asMap = mapper.readValue(jsonSource, Map.class);
and then construct your B. Jackson has only limited amount of structural conversions (simple unwrapping), by design, although there is extensive set of scalar conversions (non-structural conversions), so if you do need structural changes it may make sense to use a library that is focused on structural changes.

Related

Generic approach to deserialize Json to Object

This is a kind of specific question and I couldn't get any information on this topic in the javadoc of Gson.
Currently, I'm trying to parse an Json(1){ "foo":"bar", "bar":"foo" } to an Object Entity. Normally I would map these values to the Entity Object with the fields foo and bar, however I'd like to be more independent from the API.
For (1) I'd have
public class Entity {
String foo;
String bar;
}
But if we test another Endpoint the resulting Json (2) would look like
{ "notFoo":"bar", "notBar":"foo" }
which makes my previous constructed Entity useless, and I'd need to create a new Class with the respective fields for that.
So my actual question is:
Is there a generic (more generic than my example) approach to
push the Json into a GenericEntity -> g.fromJson(response.getBody(),GenericEntity.class); that every field of the json will be successfully mapped, even when using different Endpoints?
Alternatively, are there other dependencies which support that out of the box?
You do not have a deserialisation problem, you have a problem of not knowing how to represent possibly heterogeneous data.
There is no point of saying it should be Object as it should definitely be some type downstream of Object, possibly more than one. Solve this problem first: define all types that you may want to use for all use cases and then you will most likely see how to solve the deserialisation problem.
Surely, for any JSON text defined between {...} you can always go for Map<String, Object> where Object is one of:
further Map<String, Object> where Object follows these rules
List<Object> where Object follows these rules
String
one of atomic types or their boxed values
With the above rules you can represent more or less everything and you can write Gson deserialisers to deliver you those types based on the JSON type of each node (while iterating via the JSON tree). However, it is not really clear what use could you make of such a heterogenous untyped data structure.
You can use the annotation #serializedName as written in Multiple GSON #SerializedName per field?. But the schema must be the same, you only have alternatives to key name.

Java serialization to string

I have the following declaration of the static type Object:
Integer typeId;
//Obtaining typeId
Object containerObject = ContainerObjectFactory.create(typeId);
The factory can produce different types of container objects, e.g. Date, Integer, BigDecimal and so forth.
Now, after creating the containerObejct I need to serialize it to an object of type String and store it into a database with hibernate. I'm not going to provide Object-relational mapping because it doesn't relate to the question directly.
Well, what I want to do is to serialize the containerObject depending on it runtime-type and desirialize it later with the type it was serialized. Is it ever possible? Could I use xml-serialization for those sakes?
There are numerous alternatives, and your question is quite broad. You could:
use the native Java serialisation, which is binary, and then Base64 encode it
use an XML serialisation library, such as XStream
use a JSON serialisation library, such as Gson
One key feature you mention is that the object type needs to be embedded in the serialised data. Native Java serialisation embeds the type in the data so this is a good candidate. This is a double-edged sword however, as this makes the data brittle - if at some time in the future you changed the fully qualified class name then you'd no longer be able to deserialise the object.
Gson, on the other hand, doesn't embed the type information, and so you'd have to store both the JSON and the object type in order to deserialise the object.
XML and JSON have advantages that they're a textual format, so even without deserialising it, you can use your human eyes to see what it is. Base64 encoded Java serialisation however, is an unintelligible blob of characters.
There are multiple ways, but you need custom serialization scheme, e.g.:
D|25.01.2015
I|12345
BD|123456.123452436
where the first part of the String represents the type and the second part represents the data. You can even use some binary serialization scheme for this.

Representing JSON in Java in a type-safe way

Is there a good way to represent JSON in Java in a convenient, easy-to-use, type-safe way?
We've been doing it using Maps, Lists, and primitives. This works fine, except that we have to add a lot of checks for missing values.
Jackson has a good way of handling the problem:
JsonNode node;
// returns MissingNode if name not present, no null check required
node.path("name").asText();
Jackson's syntax is uncomfortable in other ways, though. Their classes don't implement the Map or List interfaces, and the JsonNode interface isn't modifiable.
Is there a better way?
Just to make sure you are aware of it: Jackson can bind JSON to/from Maps just fine:
Map<String,Object> map = new ObjectMapper().readValue(jsonSource, Map.class);
as well as full POJOs, like others commented:
POJO pojo = new ObjectMapper().readValue(jsonSource, POJO.class);
so that while you can certainly use JsonNode (aka Tree Model), there are alternative approaches that are often more convenient.

Converting only the first level of object tree using Jackson ObjectMapper

Is it possible to make ObjectMapper convert only the actual object without converting the rest of the object tree recursively ?
So that :
Map<String,Object> props = new ObjectMapper().convertValue(obj, Map.class);
results in a map of [field, value] where values are the actual references to instances of the fields of obj instead of Maps ?
There is no such feature right now with Jackson. You can probably achieve this with a custom Serializer/Deserializer pair that could share some data and "protocol". But, why bother doing this when the easier (and a LOT faster) way would be to have a generic way to go from POJO to Map, probably using reflection.
I am not sure I understand what you are really trying to do here.
But one thing that may help is to keep in mind that java.lang.Object type (as well as JsonNode) can be freely included in the structure, to get sort of "untyped" binding deeper in the structure. With these types, you can avoid rigid data-binding for some subsets of the object model; and possibly convert to POJOs using ObjectMapper.convertValue() more dynamically.

Create Object vs Reading Json

I'm working on an Android app. The app gets the data as JSON string (name of universities and student lists) and manipulate the app according to the data.
What will be a better approach?
Create a new Object and parse the JSON string into it, and work with the object, or
Keep the JSON string, and just use JSONObject whenever I need to grab information from the string
Or any other way?
If I'm using the new Object, how can I transfer (or share) the object with other activities in the app?
I know that for string we can use putextra().
Use objects.
I would suggest to use Jackson library,
be cause it is very fast and easy to ingrate.
You can find code examples here :
http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
P.S. : Jackson is not the only library for this approach > Jackson Vs. Gson
I almost always parse the JsonObject into a specific object E.g. class University.
One benefit of doing this, is you can put it nicely into collections. E.g. HashMaps, Set or just straight List. When dealing with it as a JsonObject you won't be able to as easily work with it.
You can do things like sort it if you Object inherits Comparable, and can define equals/toString/hashCode.
There are a number of other benefits, but I think you'll find holding that data in a real data structure will give you the most benefit
I would recommend parsing the string (or using a library to do this for you!) and filling an object. This way, your model object can control the data and how it is shared with other objects, and use internal data structures to optimize usage. If you stuck with the JSON string you'd end up parsing it multiple times to pull out data.
However you decide to share the object/string across activities shouldn't affect your decision for how to model the data. You'll likely end up passing it across activities in any case.
I suggest that you use objects too.
You can use Gson library to do any conversion between json string and objects. It is very, very easy to use. http://code.google.com/p/google-gson/
To transfer the data between other activities you can make your object implement the Serializable interface, this way you can use the .putExtra() and pass it forward.

Categories