JerseyでJSONシリアライズ対象外のプロパティを指定する (2)
JerseyでJSONシリアライズ対象外のプロパティを指定する (1)
こちらの続きです。JAX-RS(Jersey)でJavaオブジェクトをJSON形式に変換する際に、@XmlTransientをつけて対象外のプロパティを指定しましたが、今回はJacksonMixInAnnotationsを使用する方法を試してみました。この方法ではシリアライズ対象オブジェクトにアノテーション等を追加することなく、変換対象や名前等を変更することができます。
例えば、以下のようなクラスをJSONに変換するとします。
public class Person { public String name; public String emailAddress; public int age; // ... }
ここで、"age"は変換対象外とし"emailAddress"は"email"という名前に変換したいという場合には以下のようなMixinクラスを作成します。
abstract class PersonMixin { PersonMixin (@JsonProperty("email") String emailAddress, @JsonIgnore ("age") int h) { } }
この例ではコンストラクタにアノテーションをつけていますが、abstractなgetter?を定義してそこにアノテーションをつけることもできますし、PersonMixin自体に@JsonIgnoreProperties等を付けてまとめて指定することもできます。
このMixinを使用するには以下のようにします。
ObjectMapper om = new ObjectMapper(); om.getSerializationConfig().addMixInAnnotations(Person.class, PersonMixin.class); String str = om.writeValueAsString(obj);
個別のMixinを適用するのではなく、設定をまとめて管理するには、Moduleを使うことができます。
public class MyModule extends SimpleModule { public MyModule() { super("MyModule", new Version(0, 0, 1, "SNAPSHOT")); } @Override public void setupModule(SetupContext context) { super.setupModule(context); context.setMixInAnnotations(Person.class, PersonMixin.class); } }
このModuleを使用するには以下のようにします。
ObjectMapper om = new ObjectMapper(); om.registerModule(new MyModule()); String str = om.writeValueAsString(obj);
JerseyでJacksonMixInAnnotationsを使用する
JerseyでJacksonMixInAnnotationsを使用する場合には、ObjectMapperを返すProviderを作成して登録する必要があります。Providerのクラスは以下のようになります。
import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.ext.ContextResolver; import javax.ws.rs.ext.Provider; import org.codehaus.jackson.map.ObjectMapper; @Provider @Produces(MediaType.APPLICATION_JSON) public class ObjectMapperProvider implements ContextResolver<ObjectMapper> { private ObjectMapper mapper; public ObjectMapperProvider() { mapper = new ObjectMapper(); mapper.registerModule(new MyModule()); } @Override public ObjectMapper getContext(Class<?> type) { return mapper; } }
ObjectMapperはConfigurationを変更しなければスレッドセーフということなのでインスタンスを使い回しています。
TomcatなどのJAX-RSに対応していないコンテナの場合にはApplicationクラスで登録します。
import javax.ws.rs.core.Application; public class MyApplication extends Application { // ... @Override public Set<Object> getSingletons() { Set<Object> classes = new HashSet<Object>(); classes.add(new ObjectMapperProvider()); return classes; } }
これでJSONの生成にこのObjectMapperが使用されるので、MyModuleでの指定が反映されます。