I am attempting to deserialize a jackson-serialized Google Ads sdk object. In particular, I am running into issues in instantiating specific classes which behave like enums, for example :
public class CampaignStatus implements Serializable {
private String _value_;
private static HashMap _table_ = new HashMap();
public static final String _UNKNOWN = "UNKNOWN";
public static final String _ENABLED = "ENABLED";
public static final String _PAUSED = "PAUSED";
public static final String _REMOVED = "REMOVED";
public static final CampaignStatus UNKNOWN = new CampaignStatus("UNKNOWN");
public static final CampaignStatus ENABLED = new CampaignStatus("ENABLED");
public static final CampaignStatus PAUSED = new CampaignStatus("PAUSED");
public static final CampaignStatus REMOVED = new CampaignStatus("REMOVED");
private static TypeDesc typeDesc = new TypeDesc(CampaignStatus.class);
protected CampaignStatus(String value) {
this._value_ = value;
_table_.put(this._value_, this);
}
public String getValue() {
return this._value_;
}
public static CampaignStatus fromValue(String value) throws IllegalArgumentException {
CampaignStatus enumeration = (CampaignStatus)_table_.get(value);
if (enumeration == null) {
throw new IllegalArgumentException();
} else {
return enumeration;
}
}
public static CampaignStatus fromString(String value) throws IllegalArgumentException {
return fromValue(value);
}
public boolean equals(Object obj) {
return obj == this;
}
public int hashCode() {
return this.toString().hashCode();
}
public String toString() {
return this._value_;
}
public Object readResolve() throws ObjectStreamException {
return fromValue(this._value_);
}
public static Serializer getSerializer(String mechType, Class _javaType, QName _xmlType) {
return new EnumSerializer(_javaType, _xmlType);
}
public static Deserializer getDeserializer(String mechType, Class _javaType, QName _xmlType) {
return new EnumDeserializer(_javaType, _xmlType);
}
public static TypeDesc getTypeDesc() {
return typeDesc;
}
static {
typeDesc.setXmlType(new QName("https://adwords.google.com/api/adwords/cm/v201809", "CampaignStatus"));
}
}
When a Campaign object is serialized (which contains a CampaignStatus as defined above), the JSON looks like this:
"status":{"value":"ENABLED"}
The deserializer throws a mismatched input exception when trying to write a JSON campaign to a Campaign object. Since the objects are owned by Google, I can't modify the existing classes or add annotations. My solution needs to work for 250+ classes that follow this pattern, so individually wrapping or extending these isn't a feasible solution. Additionally, I will have many different stakeholders serializing these objects, so modifying how they are serialized is also not a useable solution.
What I need is some way to indicate to the deserializer that when it comes across a situation like this, it should look for the fromValue method and use that. I'm ok with explicitly stating what json keys/values would need to use such a method; I just need a more dynamic way of modifying the serialization than extending the class or adding annotations.
You can indicate factory method using #JsonCreator annotation - it is going to be used by Jackson to perform deserialization.
In your case it would look something like this:
#JsonCreator
public static CampaignStatus fromValue(#JsonProperty("value") String value) throws IllegalArgumentException {
CampaignStatus enumeration = (CampaignStatus)_table_.get(value);
if (enumeration == null) {
throw new IllegalArgumentException();
} else {
return enumeration;
}
}
I am a bit confused with what exactly you are trying to achieve but feel free to put any logic that fulfill you requirements in the method above.
So I didn't find the best possible solution, but I'll share the best I could come up with. I implemented a new generic deserializer extending JsonDeserializer, and used reflection in the deserialize method to invoke the .fromValue method. I then used reflection to search the directories for all classes, and search each class for a matching .fromValue method. Every time I successfully find a class that follows this pattern, I register it with the mapper using a new generic deserializer for the corresponding class. It's a bit costly, but I only register the deserializers at instantiation so it's ok that it's a complex.
Related
My company has an application server that receives sets of instructions in their own bespoke XTML syntax. As this is limited, there's a special "drop to Java" command that sends arguments to a JVM (1.6.0_39). Arguments are passed as "in" only, or "in/out", where the special "in/out" variables are a library of mutables for use with this platform.
Previously the only way to receive external configuration was to use a different special command to read from an XTML file. For reasons not worth delving into, this method of configuration is difficult to scale, so I'm working on a way to do this with Java.
The syntax for this configuration was two-tuples of (String,T) where String was the property name in the XTML file, and T was the in/out mutable that the application server would assign the property value to.
I'm attempting to make this transition as seamless as possible, and not have to do annoying string parsing in the application server.
I already have a function
public String[] get(String ... keys)
That retrieves the values from the application servers' keys, but What I really need is a function
public static void get(T ... args)
that accepts the two-tuples. However, note it needs to be static in order to be called from the application server, and my understanding is that T can't be used in a static context.
I'm at a loss for how to approach this problem in a way that doesn't require (at least) two steps, and there is no way to loop over the arguments in the application server.
I know I'm working within a tight set of constraints here, so if the answer is "you have to some messed up stuff", that's fine - I'd just like any insight into another way.
-- edit --
Editing a more specific example.
The configuration is a set of key-value pairs, and can be in a database or a file. The get function is:
public JSONObject get(String ... keys) throws ClassNotFoundException, SQLException, KeyNotFoundException, FileNotFoundException, IOException {
JSONObject response = new JSONObject();
if(this.isDatabase) {
for(int i=0;i<keys.length;i++){
PreparedStatement statement = this.prepare("SELECT value FROM "+this.databaseSchema+"."+this.settingsTableName+" WHERE key = ? LIMIT 1");
statement.setString(1, keys[i]);
ResultSet results = statement.executeQuery();
boolean found = false;
while(results.next()){
String value = results.getString("value");
value = value.replace("\"","");
response.put(keys[i], value);
found = true;
}
if(!found){
throw new KeyNotFoundException(keys[i]);
}
}
} else if (this.isFile) {
boolean[] found = new boolean[keys.length];
BufferedReader br = new BufferedReader(new FileReader(this.settingsFile));
String line;
while((line = br.readLine()) != null ){
String key;
String value;
for(int i=0;i<line.length();i++){
if(line.charAt(i) == '='){
key = line.substring(0,i);
value = line.substring(i+1,line.length());
if(indexOfString(keys,key) != -1){
value = value.replace("\"","");
found[indexOfString(keys,key)] = true;
response.put(key,value);
if(allFound(found)==-1){
return response;
}
}
break;
}
}
}
if(allFound(found)!=-1){
throw new KeyNotFoundException(keys[allFound(found)]);
}
}
return response;
If I had my way, it would look like ...
// ConfigurationReader.java
public class ConfigurationReader{
public ConfigurationReader( ... ){}
public static JSONObject get(String key){
// Get the key
}
}
// ConfigurationInterface.java
public static void get(T ... args){
ConfigurationReader cfgReader = new ConfigurationReader( ... );
for(var i=0;i<args.length;i+=2){
in = args[i];
out = args[i+1];
out = cfgReader.get(in);
}
}
You can use generic types in a static context. Your question is somewhat vague/unclear about how you intend to do this, but consider the example below:
public class Example {
public static void main(String[] args) {
Type t1 = new Type("foo");
Type t2 = new Type("bar");
Type t3 = new Type("baz");
Printer.<Type> printNames(t1, t2, t3);
}
public static class Printer {
#SafeVarargs
public static <T extends Type> void printNames(T... objs) {
for (T obj : objs) {
System.out.println(obj);
}
}
}
public static class Type {
private final String name;
public Type(String name) {
this.name = name;
}
#Override
public final String toString() {
return name;
}
}
}
Printer.<Type> printNames(t1, t2, t3) makes a static reference to the printNames method, parameterized with the Type generic type.
Note that this is type-safe. Attempting to pass an object of a different type into that parameterized method will fail at compile-time (assuming the type is known to be different at that point):
Example.java:8: error: method printNames in class Printer cannot be applied to given types;
Printer.<Type> printNames(t1, t2, t3, "test");
^
required: T[]
found: Type,Type,Type,String
reason: varargs mismatch; String cannot be converted to Type
where T is a type-variable:
T extends Type declared in method <T>printNames(T...)
Edit
Based on your comment, the issue isn't that you're trying use a generic type for your method argument (in the Java-sense of the word generic, anyway); you're simply looking for any non-specific, parent class that both String and your custom type inherit from. There's only one such class: Object.
I'd strongly recommend reconsidering your design if you have any flexibility, since this will make for poor API design. However you can have your method accept an arbitrary number of arbitrarily-typed objects using Object... objs.
For example:
public class Example {
public static void main(String[] args) {
Printer.printNames("a", "b", new Type("foo"), new Type("bar"));
}
public static class Printer {
public static void printNames(Object... objs) {
for (Object obj : objs) {
if (obj instanceof String) {
System.out.println(((String) obj).toUpperCase());
}
else if (obj instanceof Type) {
System.out.println(obj);
}
}
}
}
public static class Type {
private final String name;
public Type(String name) { this.name = name; }
public final String toString() { return name; }
}
}
Based on #nbrooks work, I found a solution. I made a temporary MutableString (to be replaced by the classes provided by the library).
public static class MutableString {
public String value;
public MutableString(){}
}
// One for every mutable type
public static void Pair(String key, MutableString mutable, ApplicationConfiguration appConfig) throws Exception{
mutable.value = appConfig.get(key).toString();
}
public static void Retrieve(Object ... args) throws Exception {
ApplicationConfiguration appConfig = new ApplicationConfiguration( ##args## );
for(int i=0;i<args.length;i+=2){
if(args[i+1].getClass().equals(new MutableString().getClass())){
ApplicationConfiguration.Pair( (String) args[i], (MutableString) args[i+1], appConfig);
} // One for every mutable type
}
}
Let's say I have these set of POJO class that implement an interface but there are no common attributes here.
public interface MainIfc {}
class Ifc1 implements MainIfc {
private String a1;
public String getA1() {
return a1;
}
public void setA1(String a1) {
this.a1 = a1;
}
}
class Ifc2 implements MainIfc {
private String x1;
private String x2;
public String getX1() {
return x1;
}
public void setX1(String x1) {
this.x1 = x1;
}
public String getX2() {
return x2;
}
public void setX2(String x2) {
this.x2 = x2;
}
}
And in conjunction with these POJO classes I have a couple of methods which I can use to retrieve the type of POJO being returned based on another value and the actual POJO with values.
public class GetIfc {
public Class getIfcType(int code) {
if (code==1)
return Ifc1.class;
else
return Ifc2.class;
}
public MainIfc getIfc(int code) {
if (code==1) {
Ifc1 thisIfc = new Ifc1();
thisIfc.setA1("Ifc1");
return thisIfc;
} else {
Ifc2 thisIfc = new Ifc2();
thisIfc.setX1("Ifc2");
thisIfc.setX2("Ifc2");
return thisIfc;
}
}
}
Is there a way using which I can read the concrete POJO safely in my code and use the getters/setters? I have gone through quite a few questions which provide answers based on Reflection but that isn't working for me. The getters/setters aren't visible and when I call .getClass() on the returned Object I see it is the MainIfc interface.
The design problem I am trying to solve pertains to a REST API automation framework that I am trying to design. Basically I have a ClientResponse parser which will send back the POJO I am looking for. But I don't want the folks writing the test cases to worry about the type of POJO that is returned. So I was thinking I could return the type and the instantiated POJO so I get the values but I am troubled over how to achieve this dynamically.
Try this code. Maybe this will return all the methods in class as well as methods inherited from Object class.
public static void main(String[] args) throws ClassNotFoundException {
GetIfc getIfc=new GetIfc();
MainIfc clas1s=getIfc.getIfc(1);
Class class1= clas1s.getClass();
System.out.println(class1);
Method[] mem= class1.getMethods();
for(Method mmm : mem) {
System.out.println(mmm.getName());
}
}
Do consumers of MainIfc actually need the POJOs, or just the data inside of them?
It might be cleaner design if MainIfc declares a method or two that exposes the data that its consumers will need. Your POJOs can then implement the methods that the MainIfc interface declares. Or you can build a wrapper class for each POJO that conforms it to the interface, if you want to keep the concerns of implementing your interface separate from your POJOs.
Ideally an interface should expose a few methods that can be used to interact with any class which implements it and no one should need to know about the underlying POJOs/implementation.
public interface MainIfc {
public Hash getAttributes();
public setAttributes(Hash attributes);
}
class Ifc1 implements MainIfc {
private String a1;
public String getA1() {
return a1;
}
public void setA1(String a1) {
this.a1 = a1;
}
public Hash getAttributes() {
// return a hash with data that MainIfc consumer will need from this POJO
}
public setAttributes(Hash attributes) {
// copy hash attributes to corresponding POJO fields
}
}
class Ifc2 implements MainIfc {
private String x1;
private String x2;
public String getX1() {
return x1;
}
public void setX1(String x1) {
this.x1 = x1;
}
public String getX2() {
return x2;
}
public void setX2(String x2) {
this.x2 = x2;
}
public Hash getAttributes() {
// return a hash with data that MainIfc consumer will need from this POJO
}
public setAttributes(Hash attributes) {
// copy hash attributes to corresponding POJO fields
}
}
It sounds to me like you're trying to do something rather illogical. Strategy Pattern or Abstract Factory might be a good fit for your requirement, but at the moment I don't quite understand what exactly it is you're trying to achieve. You should definitely not be conditionally casting and calling different methods on these classes. If you really want to continue on this path, I would suggest going with reflection, if not an option, and you need the flexibility, I'd probably go with a Map of some kind.
But I would definitely rethink your design if at all possible.
Try this piece of code, I don't know if I fully understand your requirement but based on my understanding I think below code would do the trick.
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
GetIfc getIfc = new GetIfc();
MainIfc clas1s = getIfc.getIfc(1);
Field[] fields = clas1s.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
Class fieldClasslasse = field.getType();
if (field.getModifiers() == Modifier.PRIVATE) {
// you need to check fieldClass, if it is boolean then initials of the getter could be 'is' instead of 'get'
String methodNameGet = "get" + Character.toUpperCase(field.getName().charAt(0))
+ field.getName().substring(1);
String methodNameSet = "set" + Character.toUpperCase(field.getName().charAt(0))
+ field.getName().substring(1);
Method methodGet = clas1s.getClass().getDeclaredMethod(methodNameGet, null);
Object value = methodGet.invoke(clas1s, null);
if (value != null && value instanceof String) {
String valueUpper = ((String)value).toUpperCase();
Class[] cArg = new Class[1];
cArg[0] = String.class;
Method methodSet = clas1s.getClass().getDeclaredMethod(methodNameSet, cArg);
Object[] var = new Object[1];
var[0] = valueUpper;
methodSet.invoke((Object) clas1s, var);
}
}
}
}
A little explanation about above code : Get all the fileds of the object and check if is a private property, if yes then it must have a public getter and setter, guess their name based on java convention, call the getter, get the value, check if it is a instance of String class, if yes make it UPPERCASE then call setter to set new value.
I have some Data Objects e.g. Task, Resource etc.
These Objects hold domain data e.g.
public class Task{
private int Id;
private String taskName;
.......
//getters and setters here
//in addition they have a special method dynamically to get values i.e. There is a reason for this
public static String runGetter(Task task, String getter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for (Method method : task.getClass().getMethods()) {
if (method.getName().toLowerCase().equalsIgnoreCase(getter.toLowerCase())) {
if (method.getReturnType().isPrimitive()) {
StringBuilder sb = new StringBuilder();
sb.append(method.invoke(task));
return sb.toString();
}
if (method.invoke(task) != null) {
return method.invoke(task).toString();
}
}
}
return null;
}
}
}
Now I have some methods that take these objects and write them out to streams
e.g.
public class WriterUtil{
public void write(Task task, File outputFile){
//write the task object out.
}
public void write(Resource resource, File outputFile){
//write the resource object out
}
....
}
The write methods call another method to get data out of the object as follows. (Yes, it can be made more efficient but it is not the core of my problem)
public class WriterUtil {
.....
public static String extractLine(Task task, LinkedHashMap<String, String> columns, String delimiter) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
StringBuilder sb = new StringBuilder();
Iterator<String> itr = columns.keySet().iterator();
while (itr.hasNext()) {
String getter = "get" + itr.next();
String value = Task.runGetter(task, getter);
if (value == null)
value = "";
sb.append(value + delimiter + " ");
}
return sb.toString().substring(0, sb.lastIndexOf(delimiter)).trim();
}
......
}
My Main problem is this given the described scenario above, I find myself writing the same identical code for each domain object e.g.
public void write(Task task, File outputFile)
public void write(Resource resource, File outputFile)
//etc ....
I repeat the same for extractLine.
As you can see I am duplicating the same code for each domain object. Where the only thing varying is the actual domain object. These methods do the exact same thing with each domain object.
My Question is; if I am to refactor these methods and write one method each to apply to every domain object, what are my best options.
Should I have the domain objects implement an interface? This seems rather cumbersome and I am not sure it is the right course of action.
Can I use generics? I expect it is probably the best practice but I have very limited experience with how to go about generifying (Is that a word?) my Domain Objects and these common methods. Can someone offer a re-write of my above code on how they would modify them for generic?
Do I have a third option?
Move the reflection code into a utility type and change the signature to:
public static String runGetter(Object bean, String getter)
The Task type isn't used at all inside the method.
Likewise, the only reason you need a Task type here is because the other call requires it:
public static String extractLine(Object bean, Map<String, String> columns,
String delimiter)
You'll need to use an interface; generics can't be employed here (you could do it in C++ with templates, but not in Java).
If you don't want you objects to implement the interface, you can create helper objects for each of your domain classes; those helper objects would implement an interface with the extractLine() function:
class TaskExtractLine implements IExtractLine
{
public TaskExtractLine(Task task)
{
this.task = task;
}
public String extractLine(LinkedHashMap<String, String> columns, String delimiter)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
return WriterUtil.extractLine(task, columns, delimiter);
}
private Task task;
}
Then you'll have the write function like this: public void write(IExtractLine extractLineHelper, File outputFile) and call it like this: write(new TaskExtractLine(task), outputFile).
I have been trying to create an XML using the simplexml library (v2.6.2)
http://simple.sourceforge.net/home.php
The XML I want to create has to hold an enum value, which should be case-sensitive. Following is the POJO :
package pojos;
public enum MyEnum {
NEW("new"),
OLD("old");
private final String value;
MyEnum(String v)
{
value = v;
}
public String value() {
return value;
}
public static MyEnum fromValue(String v) {
for (MyEnum c: MyEnum.values()) {
if (c.value.equals(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
Following is the serializer code :
import java.io.File;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import pojos.MyEnum;
public class TestEnum {
/**
* #param args
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Serializer serializer = new Persister();
MyEnum example = MyEnum.NEW;
File result = new File("myenum.xml");
serializer.write(example, result);
}
}
The resultant output :
<myEnum>NEW</myEnum>
The desired output :
<myEnum>new</myEnum>
How should I proceed ? I cannot change the variable name in the enum as it happens to be the keyword "new" !
Thanks.
After some investigation of the source code, i have discovered that the library uses interface Transform to transform values to Strings. The default behavior of enum transformations is defined by class EnumTransform. In order to customize that, you can define you own Transform class. The following version of Transform implementation would call toString() instead of the default name() on the enum objects.
class MyEnumTransform implements Transform<Enum> {
private final Class type;
public MyEnumTransform(Class type) {
this.type = type;
}
public Enum read(String value) throws Exception {
for (Object o : type.getEnumConstants()) {
if (o.toString().equals(value)) {
return (Enum) o;
}
}
return null;
}
public String write(Enum value) throws Exception {
return value.toString();
}
}
Transform objects are returned from match method by objects of Matcher interface. There could be several Matcher objects. The library tries them one by one until it finds one that returns a non-null Transformer object. You can define your own Matcher object and pass it as argument to the constructor of Persister class. This object will get the highest priority.
Persister serializer = new Persister(new Matcher() {
public Transform match(Class type) throws Exception {
if (type.isEnum()) {
return new MyEnumTransform(type);
}
return null;
}
});
Finally, you wont forget to define a toString method on your enum classes. Then the combination of codes above will do you the work of encoding enum objects using their toString values.
You should override toString()
#Override
public String toString() {
return this.value.toLowerCase();
}
Then write results using
serializer.write(example.toString(), result);
I would look at the serializer code and undestand what that is doing, as you have not annotated any of your fields...which (according to their docs) should throw an an exception.
Can I write a generic method to trim all strings within an complex object (object containing other objects)? Should java reflection api be used to achieve this?Thanks.
I have provided a sample below. However in reality there could be multiple objects within objects. Each object might contain a collection of String or collection of other objects which may contain String. Is there a way to trim the Strings - ones directly with the objects and ones within collection.
public class School{
private List<Course> courses;
private List<Student> students;
// Getters and Setters
}
public class Course{
private String name;
private String xxx;
private String yyy;
private List<String> zzzList;
}
public class Student{
private Map<String,String> xxx;
private List<Course> courseList;
}
Yes, reflection is the way. Basically, you need to:
get the class of the top level object (with [object].getClass())
get all the fields of the object (with clazz.getFields() - beware, it works only with public fields)
check if the field is String (either get field.getType() and check it's a string, or do a field.get(the object) and a instanceof String)
if it's the case, replace the string in the object with the trimmed one, using field.set([your object],[trimmed string])
if the field is an object but not a string, call your method recursively
That will do the trick.
---- just seen your update
Trimming strings in collection will be more tricky, since the strings are not exposed as public fields of the collection (List for example).
You will need something more clever, that will check if an object is an instance of List, or Map, or etc... (or a derived class!).
Main problem is also that java generics are done with erasing type at compile type. So you cannot know that your field is List[String] or List[Integer] or whatever. Every List[?] becomes List.
Still you can try to do it like that:
if field type is List
iterate through the list values
if a value is instanceof String, you have to remove it from the list and insert in place the trimmed version
if a value is an object, there you go again recursively with your method.
Not very interesting in real life samples, but more on a library side maybe.
Long way to go though!
Yes, you can do that with reflection, quite easily. Just check if the field is instanceof String.
The exact way to do it depends on your object structure.
/*********************************************************************************************
* Trim first level children of string type in this object
* #param obj which all string properties to be trimmed
*********************************************************************************************/
public static void trimAll(final Object obj)
throws LocalException
{
if (obj==null) return;
final Class c = obj.getClass();
final Method[] methods = c.getMethods();
final Class[] SETTER_ARGS = new Class[]{String.class};
final Object[] SETTER_VAL = new Object[1];
final String SET = "set";
final String GET = "get";
final String SPACE = "\u0020";
final String TAB = "\t";
for (final Method m:methods)
{
try
{
final String name=m.getName();
if (
name.length()>GET.length()
&& name.indexOf(GET)==0
&& m.getReturnType().equals(String.class)
&& m.getParameterTypes().length==0)
{
final String v = (String)m.invoke(obj);
if (v!=null && (v.contains(SPACE) || v.contains(TAB)) )
{
final Method setter=c.getMethod(SET+name.substring(3),SETTER_ARGS);
if (setter!=null)
{
SETTER_VAL[0]=v.trim();
setter.invoke(obj,SETTER_VAL);
}
}
}
}
catch (final Throwable e)
{
throw new LocalException(LocalException.EC_GENERAL_EXCEPTION,e);
}
}
}
We can also use Jackson to serialize and then deserialize the object. While deserializing we can use custom deserializer to trim all the String values.
Create a deserializer like this:
public class TrimStringToNullDeserializer extends JsonDeserializer<String> {
#Override
public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
String value = jsonParser.getValueAsString();
if (isNull(value)) {
return null;
}
value = value.trim();
if (value.length() == 0) {
value = null;
}
return value;
}
And then we can use Jackson to trim all values:
public class TrimStringToNullConfiguration {
private ObjectMapper objectMapper;
public Client trimToNull(Client inputClient) throws JsonProcessingException {
return getObjectMapper().readValue(getObjectMapper().writeValueAsString(inputClient), Client.class);
}
private ObjectMapper getObjectMapper() {
if (isNull(objectMapper)) {
objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new TrimStringToNullDeserializer());
objectMapper.registerModule(module);
}
return objectMapper;
}
I have placed a working example over here.
private <T> T toTrim(T t) {
Field[] fields = t.getClass().getFields();
for (Field field : fields) {
try {
if (field.get(t) instanceof String) {
Object o = field.get(t);
String s = (String) o;
field.set(t, s.trim().toUpperCase());
}
} catch (IllegalAccessException e) {
log.info("Error converting field "+ field.getName() );
}
}
return t;
}
if (yourObject instanceof String){
yourObject = yourObject.trim();
}
Hope it helps :)