I have a simple data service :
@GET
public Data getData(@QueryParam("id") Long id) {
Data data = dataService.getData(id);
return data;
}
And a matching DataSerializer
that implements JsonSerializer<Data>
:
The DataSerializer
is registered to Jackson via :
simpleModule.addSerializer(Data.class , dataSerializer);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(simpleModule);
It works well.
But today , I want to add another Locale
parameter , and hope the DataSerializer
to output correspondent content :
@GET
public Data getData(@QueryParam("id") Long id , @QueryParam("locale") Locale locale)
The 'Data
' itself contains various locale variations , and I hope to get the assigned locale output.
But when I get the locale
from the parameter , I don't know how to pass the locale
value to the DataSerializer
…
Is there anyway to achieve this ?
Except this solution :
Data data = dataService.getData(id.get() , locale);
which is not what I want.
It seems ThreadLocal
is the only way to achieve this , but I feel that is ugly. Any other feasible solutions ?
Thanks.
Environments : dropwizard-0.7.0-rc2 , jackson-core:jar:2.3.1
===================== updated ==========
reply to @andrei-i :
Because my data itself already contains various locale versions. for example :
Data helloData = dataService.get("hello");
helloData.getName(Locale.English) == "Hello";
helloData.getName(Locale.France) == "Bonjour";
helloData.getName(Locale.Germany) == "Hallo";
I want to directly pass the locale from URL to JsonSerializer , to get one version of the data presentation.
And there 'may' be other version (not just locale) , so , inheriting Data mixing Locale is not considered.
I know that this is not a new question but here is what I came up with facing the similar problem:
created custom annotation:
@Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface JsonLocalizable { public String localizationKey(); }
Jackson serializer:
public class LocalizingSerializer extends StdSerializer<String> implements ContextualSerializer { private String localizationKey; public LocalizingSerializer() { super(String.class); } public LocalizingSerializer(String key) { super(String.class); this.localizationKey = key; } @Override public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { String localizedValue = //.... get the value using localizationKey jgen.writeString(localizedValue); } @Override public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { String key = null; JsonLocalizable ann = null; if (property != null) { ann = property.getAnnotation(JsonLocalizable.class); } if (ann != null) { key = ann.localizationKey(); } //if key== null?? return new LocalizingSerializer(key); } }
Annotate the field you want to localize:
public class TestClass { @JsonSerialize(using = LocalizingSerializer.class) @JsonLocalizable(localizationKey = "my.key") private String field; public String getField() { return this.field; } public void setField(String field) { this.field = field; } }
Solution 1. In your JAX-RS implementation register your own implementation of MessageBodyWriter for JSON requests. Probably your implementation will extend Jackson. Also it might be possible that you will have to unregister Jackson. In a MessageBodyWriter
you can inject a UriInfo instance using the @Context
annotation, and with it you can get any request parameter.
Solution 2. Change the architecture of your Data
, so that it is locale-aware. For example, create a setter setLocale()
which will change the returned data, if the locale was set.
来源:https://stackoverflow.com/questions/22634860/how-to-pass-parameter-to-jsonserializer