Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson - Modify an attribute at runtime without annotation

Tags:

java

json

jackson

Let's say I have a bean:

public class Msg {
  private int code;
  private Object data;

   ... Getter/setters...
}

And I convert it into JSON or XML with this kind of test code:

public String convert() {
  Msg msg = new Msg();
  msg.setCode( 42 );
  msg.setData( "Are you suggesting coconuts migrate?" );

  ObjectMapper mapper = new ObjectMapper();
  return mapper.writeValueAsString( msg );
}

The output will be somehow like that :

{"code":42,"data":"Are you suggesting coconuts migrate?"}

Now let's say I want to replace the 'data' attribute with some dynamic name:

public String convert(String name) {
  Msg msg = new Msg();
  msg.setCode( 42 );
  msg.setData( "Are you suggesting coconuts migrate?" );

  ObjectMapper mapper = new ObjectMapper();
  // ...DO SOMETHING WITH MAPPER ...
  return mapper.writeValueAsString( msg );
}

If I call the function convert( "toto") I woukld like to have this output:

{"code":42,"toto":"Are you suggesting coconuts migrate?"}

If I call the function convert( "groovy") I woukld like to have this output:

{"code":42,"groovy":"Are you suggesting coconuts migrate?"}

Of course I could do a String replace after JSON creation, but if you have an answer with a programmatic approach I'll take it.

Thanks

like image 955
Julien Revault d'A... Avatar asked Sep 20 '13 11:09

Julien Revault d'A...


1 Answers

You can use PropertyNamingStrategy class to override class property. See simple implementation of this class:

class ReplaceNamingStrategy extends PropertyNamingStrategy {

    private static final long serialVersionUID = 1L;

    private Map<String, String> replaceMap;

    public ReplaceNamingStrategy(Map<String, String> replaceMap) {
        this.replaceMap = replaceMap;
    }

    @Override
    public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
        if (replaceMap.containsKey(defaultName)) {
            return replaceMap.get(defaultName);
        }

        return super.nameForGetterMethod(config, method, defaultName);
    }
}

Example program could look like this:

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;

public class JacksonProgram {

    public static void main(String[] args) throws IOException {
        Msg msg = new Msg();
        msg.setCode(42);
        msg.setData("Are you suggesting coconuts migrate?");

        System.out.println(convert(msg, "test"));
        System.out.println(convert(msg, "toto"));
        System.out.println(convert(msg, "groovy"));
    }

    public static String convert(Msg msg, String name) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setPropertyNamingStrategy(new ReplaceNamingStrategy(Collections.singletonMap("data", name)));
        return mapper.writeValueAsString(msg);
    }
}

Above program prints:

{"code":42,"test":"Are you suggesting coconuts migrate?"}
{"code":42,"toto":"Are you suggesting coconuts migrate?"}
{"code":42,"groovy":"Are you suggesting coconuts migrate?"}
like image 151
Michał Ziober Avatar answered Nov 04 '22 13:11

Michał Ziober