Jackson automatically map properties named #foo? - java

When playing with REST, my provider is generating JSON with attribute names starting with an at sign when the property is marked as #XmlAttibute like this:
#XmlAttribute
int foo = 1;
will return
{"#foo":1}
How can I tell Jackson for deserializing that if I have on the client
int foo;
that it should take the json-Attribute #foo for this. Or in more general terms: how to tell Jackson to ignore the # when deserializing?
Update: I know about #JsonProperty("#foo") annotation that StaxMan is referring - I forgot to put that in my original question, as I was especially interested in a "global setting" and not on a per property level.

Easiesti thing might be to disable adding those '#' signs there as they seem useless. I know some XML-to-JSON libs (Jettison) want to use this to differentiate between XML attributes and elements, but it's of little use with actual JSON processing.
But Jackson can be given expected property name in JSON with #JsonProperty annotation:
#JsonProperty("#foo")
public int foo; // or add in setter
if it is necessary to keep those at signs in there.

I think you want #XmlElement rather than #XmlAttribute. Values for the latter are always given a # at the beginning.

Related

How to convert json string keys from camel case to snake case in spring application [duplicate]

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;}

Apply filter on all annotated fields of a POJO (Java)

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.

Jackson serialization and remove empty space

I have some code that pulls data from a DB and populates a POJO. That POJO then gets serialized and pushed into an elasticsearch cluster.
The problem I am having is that one of the fields in the database was free text and people just put in a to get around the required field.
I'd like to be able to strip that whitespace out when pushing to elastic.
Here's an example of my pojo
public class Destination {
Long id;
...
...
String Address;
}
I am using Jackson to turn this into JSON using the ObjectMapper class. ie
mapper.convertTo(dest, Map.class)
When I view the value in elastic I am seeing:
{"id":1, ..., "address": " "}
Ideally, in this case, I'd just like to see the "id" property since the "address" is essentially null.
I've tried using ObjectMapper's serialization properties, but nothing seems to be working. Is there a standard way that this is being handled? How does Spring handle this?
I've seen similar questions asked (Jackson Json Serialization : Remove Blank strings), but I'm not sure how to apply that solution globally, rather than just at the class level, or if you can apply it globally.

How to accept multiple types in Java annotation parameter?

I would like to use an annotation on a key string to configure the initial value for a property of that key. E.g.,
#NodeProperty(initialValue = "bar") static final String "FOO";
Other code later processes the annotation, adding a key "FOO" with value "bar" to a particular key-value store, if key "FOO" doesn't already exist.
My annotation declaration is:
#Retention(RetentionPolicy.RUNTIME)
#interface NodeProperty {
long initialValue(); // I want to accept Strings, ints, byte[], etc. here.
}
But, I don't know the type of initialValue ahead of time. I'd like to accept all primitives, Strings, and arrays of the these.
Any ideas on how to accomplish this?
Edit:
Unfortunately, it sounds like overloading the annotation parameter isn't currently possible. The answers below contain various workarounds.
Accept a single type (likely String) and use type conversion to get it from what-you-got to what-the-field-is. Similar to how Commons BeanUtils or XWork allow registering type converters to get from string form values to arbitrary Java classes.
You could have different properties for different types, and then check to see which one has a value in your code. So instead of initialValue, you might have initialInt, initialString, initial(...). Cumbersome, but the only other way I can think of is to always use a String value and then parse the specific type from it.
Another option might be to reverse your declaration. Have the key in the annotation, and the value as the variable being annotated?

Jackson - suppressing serialization(write) of properties dynamically

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.

Categories

Resources