I am trying to convert java object to JSON object in Tomcat/jersey using Jackson. And want to suppress serialization(write) of certain properties dynamically.
I can use JsonIgnore, but I want to make the ignore decision at runtime. Any ideas??
So as an example below, I want to suppress "id" field when i serialize the User object to JSON..
new ObjectMapper.writeValueAsString(user);
class User {
private String id = null;
private String firstName = null;
private String lastName = null;
//getters
//setters
}//end class
Yes, JSON View is the way to go.
If you e.g. need to let the client to decide which fields to marshal, this example might help: http://svn.codehaus.org/jackson/tags/1.6/1.6.3/src/sample/CustomSerializationView.java
Check
ObjectMapper.configure(SerialiationJson.Feature f, boolean value)
and
org.codehaus.jackson.annotate.JsonIgnore
annotation
This will work only when you want all instances of a certain type to ignore id on serialization. If you truly want dynamic (aka per instance customization) you will probabily have to hack the jackson library yourself.
I don't see any way of doing that. If you need to dynamically decide which properties are marshalled, then I suggest you manually construct a Map of keys to values for your objects, and then pass that Map to Jackson, rather than passing the User object directly.
Have you tried using JSON Views?
Views allow annotation-based mechanism for defining different profiles, so if you just need slightly differing views for different users, this could work for you.
Related
I've just started to learn about serialization/deserialization and I'm a bit confused about which type is used where and when... let me explain:
I have an object containing many fields some of which are full of "useless" info.
Now, when I log the contents of such object for debugging purposes I would like the output to be in a nice json format.
So in the toString() method of this object I do the following:
import com.fasterxml.jackson.databind.ObjectMapper;
...
...
#Override
public String toString() {
ObjectMapper objectMapper = new ObjectMapper();
String s = "";
try{
s = objectMapper.writeValueAsString(this);
} catch (Exception e) {
}
return s;
}
but this also logs all the useless fields.
So I've looked around and found the #JsonIgnore annotation from com.fasterxml.jackson.annotation.JsonIgnore which I can put on top of the useless fields so as not to log them.
But from what I've understood serialization is a process of transforming a java object into a bytestream so that it can be written to file, saved in session, sent across the internet. So my noob question is: is it possible that using the #JsonIgnore annotation on top of certain fields will result in those fields not being saved into session (I use an hazelcast map), or not being sent in the http responses I send, or not being written to a file If I ever decide to do that?
If the answer to the previous question is NO, then is that because those types of actions (saving in session, writing to file, sending as http response) use different types of serialization than objectMapper.writeValueAsString(this); so they don't conflict?
In your case, you're using Jackson's ObjectMapper to convert your object to a string representation (in JSON format). The #JsonIgnore annotation is part of Jackson's annotations and will prevent fields annotated with it from being included in the JSON representation of your object.
However, this only affects the string representation created by the ObjectMapper, not other forms of serialization/deserialization. If you want to persist the object in a specific way, you may need to use a different form of serialization (such as binary serialization) or create a custom representation that excludes the fields you don't want to save.
So to answer your questions:
No, using #JsonIgnore will not affect the object saved in a session or sent as an HTTP response.
Yes, that's correct. Different forms of serialization/deserialization may handle fields differently, even if they are part of the same object.
I'm using GSON to convert JSON data I get to a Java object. It works pretty well in all my tests.
The problem is that our real objects have some properties named like is_online. GSON only maps them if they are named totally equal, it would be nice to have GSON convert the names to Java camel case isOnline.
It seems this is possible while creating the JSON data, camel case is converted to underscore separated words in JSON. But I can't find a way to specify this the other way round.
I have found the following setting works perfect when reading json with underscored attributes and using camelcasing in my models.
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create()
You can use the SerializedName annotation:
#SerializedName("field_name_in_json")
private final String fieldNameInJava;
Note: When you have set a FieldNamingPolicy already, SerializedName will overwrite its settings for that specific field (quite handy for special cases).
Bear in mind your example is an edge case. If you have a property 'foo' its getter should be named 'getFoo', and if you have a property named 'foo_bar' its getter should be named 'getFooBar', however, in your example you're mapping a boolean and booleans have special case naming conventions in java. A primitive boolean property named online should have a getter named 'isOnline', NOT 'getOnline' or even worse, 'getIsOnline'. A boolean wrapper object (i.e. Boolean) should not follow this special case and a property named 'online' should have a getter named 'getOnline'.
Hence, having boolean properties with 'is' in the name is an edge case, where you'll want to strip out this particular prefix during your conversion. In the reverse direction, your code may want to inspect the json object for both a raw property name as well as a 'is_XXX' version.
I think what you want is here. Using annotations you can tell GSON that the mySuperCoolField is actually called this_field_is_fun in the JSON and it will unpack it correctly. At least I think it works for deserialization too.
If that doesn't work, you can use custom JsonSerializer/JsonDeserializers, which work great, but you have to update them for changes in your class (like when you add a field). You lose the auto-magic.
The easiest thing to do (which would be ugly, but very clean and simple if the first suggestion doesn't work) would be to simply name the field in a way to make GSON happy, and add extra accessor methods with the names you like, e.g.
public boolean isXXX() {return this.is_XXX;}
Imagine that there are such kind of POJO classes, that just keep data:
public class Pojo() {
#AnnotatedProp
String someField;
SubPojo someSubPojo;
String someOtherFieldA;
String someOtherFieldB;
}
public class SubPojo() {
#AnnotatedProp
String someSubField;
Integer someOtherFieldC;
}
someField of Pojo and someSubField of SubPojo are marked special with the #AnnotatedProp property.
I'd like to modify an object of type Pojo. All String fields with #AnnotatedProp annotation should be modified. A "filter" should modify the values of these fields, e.g. replace some characters inside.
I tried with FieldUtils / simple reflection, but I ended up in stack overflows (the exception AND this forum).
What would be the best way to filter these fields?
Thanks for help.
I've written a recursive POJO filter/transformer doing just that, because I needed it for a project. Just cleaning up and getting green light for release, but the key points are:
use FieldUtils.readField(field, node, true) for traversal - for getting all fields annotated with your Annotation, there is also a direct method FieldUtils.getFieldsListWithAnnotation() but I needed a more flexible way to scan all nodes first, so I can drill down on sub objects
you need to check against your own base package name to identify your custom POJO classes and only traverse those sub objects.
once you have your annotated field, you can simply use FieldUtils.writeField(field, node, getMyValueForField(field), true);
Caveats:
to avoid a StackOverflow for back-references (child->ancestor), I keep a HashMap and store the FQCN of the nodes I traverse into
before rolling my own, I checked Apache commons ObjectGraphIterator, but found it not suitable for my purpose.
I have an object the represent an entity. By example i have the "user" java object that have the followings field, String name, String first name, String address, boolean deadOrAlive. But now instead of having field i want to put them into a hashmap, so my first reflex was to make it this way :
private HashMap<String, Object> fieldsHM;
This would means that i have to cast my HM value when i want to use it and i don't want to make that because i need to know the type before i use my value. I want to make something like :
Set<String> keys = fieldsHM.keySet();
for(String key : keys) {
if(fieldsHM.get(key).isBoolean()) {
// Do the appropriate things
} else {
// Do the thing for this case...
}
}
I think it's possible in java, would this be good to do it this way ?
EDIT 1: I don't want to make a hashMap because this is not what i need. What i need is a way to browse the fields of the Entity user fields by fields, and depending the type of the field do the appropriate things.
I don't want to make a hashMap because this is not what i need. What i
need is a way to browse the fields of the Entity user fields by
fields, and depending the type of the field do the appropriate things.
I guess that would be a job for Reflection, like User.class.getFields().
It will still be uncomfortable to distinguish between primitive field, but you could use their wrapper classes instead.
But whatever path you choose, I think there would be a better solution if you would state what the actual goal is.
Depending on your actual use case, it might make sense to use JSON (maybe with databind) or even a database.
You could use the heterogeneous container pattern, but I would abandon the map idea and use a proper object.
I want to parse json from a server and place it into a class. I use json4s for this. The issue is that a json object contains too many fields, it's about 40-50 of them, some of them have the long names.
I wonder, what will be a sensible way to store all of them, will I have to create 40-50 fields in a class? Remember, some of them will have the long names, as I said earlier.
I use Scala, but a Java's approach might be similar to it, so I added a tag of Java also.
I don't know json4s but in Jersey with Jackson, for example, you can use a Map to hold the Json data or you can use a POJO with all those names.
Sometimes its better to have the names. It makes the code much easier to understand.
Sometimes its better to use a Map. For example, if the field names change from time to time.
If I recall it correctly, using pure Jackson you do something like this:
String jsonString = ....; // This is the string of JSON stuff
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory); // A Jackson class
Map<String,Object> data = mapper.readValue(jsonString, HashMap.class);
You can use a TypeReference to make it a little cleaner as regards the generics. Jackson docs tell more about it. There is also more here: StackOverflow: JSON to Map
There are generally two ways of parsing json to object
1) Parse json to object representation.
the other which might suit you as you mention that your object has too many fields is amap/hashtable, or you could just keep it as JObject, an get fields ehrn you need them