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.
Related
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.
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.
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.
I am deserialising a json object as below
{
"b":"value1",
"a":"value2",
"d":"value3",
"c":"value4",
"f":"value5",
"e":"value6"
}
But i am getting ClassCastException as below
java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
My deserialisation code is
LinkedHashMap<String, String> map = new JSONDeserializer<LinkedHashMap<String, String>>().deserialize(JSONstring);
But when i use HashMap instead of LinkedHashMap it works but output gets sorted as below (Its not original order).
{
a=value2,
b=value1,
c=value4,
d=value3,
e=value6,
f=value5
}
I want to get the output in original order.
I found this related link
Flex JSON unable to properly serialize/deserialize LinkedHashMap
but didn't get how to use ObjectFactory.
I would appreciate any help!
Thanks in advance!
(Disclaimer: I just downloaded flexjson and debugged through its source code, so my answer might be slightly incomplete.)
In short:
You generally cannot get the entries in original order using flexjson.
Even writing a custom ObjectFactory will not work.
This is most likely intended and correct.
In detail:
First, the use of generics in new JSONDeserializer<LinkedHashMap<String,String>>() only affects the compilable code, flexjson cannot use this information to actually return a LinkedHashMap<String,String> (this is because the compiler removes the generic and the implementing class has no information of this generic type at runtime).
So, looking deeper into what happens during deserialization, it seems that during parsing the input string, the data is automatically converted to the correct type (string, date, number, list, etc.). This is done using some kind of autodetection of the required data type, because JSON does not provide type information in its data, so flexjson has a build-in list to support data types. It can also use custom mappings to assign values to object properties when proper class information is given (on serialization, flexjson adds a field class to the data to store this type information; or you can manually set this, see documentation).
But the main point is that - according to http://json.org -
An object is an unordered set of name/value pairs.
flexjson internally uses an (unordered) map to store the temporary object keys and values. Even if you tell flexjson to return the data as a LinkedHashMap the data is yet put into a HashMap before it will be converted to a LinkedHashMap, so the original order is not available at that point. (This might be fixed by replacing the map creation in flexjson.JSONTokener, line 442 with a LinkedHashMap but I didn't try that myself.)
Conclusion:
It looks like this behaviour even cannot be changed by providing a custom ObjectFactory, so as far as I understand the code, you cannot retain the original field order. (May I ask why this is important for your project?)
So, if anybody finds a solution anyway, don't hesitate to correct me.
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