如何将参数传递给 JsonSerializer?
Posted
技术标签:
【中文标题】如何将参数传递给 JsonSerializer?【英文标题】:How to pass parameter to JsonSerializer? 【发布时间】:2014-05-03 07:29:54 【问题描述】:我有一个简单的数据服务:
@GET
public Data getData(@QueryParam("id") Long id)
Data data = dataService.getData(id);
return data;
还有一个匹配的 DataSerializer
实现 JsonSerializer<Data>
:
DataSerializer
通过以下方式注册到 Jackson:
simpleModule.addSerializer(Data.class , dataSerializer);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(simpleModule);
效果很好。
但是今天想再添加一个Locale
参数,希望DataSerializer
能输出对应的内容:
@GET
public Data getData(@QueryParam("id") Long id , @QueryParam("locale") Locale locale)
“Data
”本身包含各种语言环境变化,我希望得到分配的语言环境输出。
但是当我从参数中获取locale
时,我不知道如何将locale
值传递给DataSerializer
...
有没有办法做到这一点?
除了这个解决方案:
Data data = dataService.getData(id.get() , locale);
这不是我想要的。
似乎ThreadLocal
是实现这一目标的唯一方法,但我觉得那很难看。还有其他可行的解决方案吗?
谢谢。
环境:dropwizard-0.7.0-rc2,jackson-core:jar:2.3.1
======================更新==========
回复@andrei-i:
因为我的数据本身已经包含各种语言环境版本。 例如:
Data helloData = dataService.get("hello");
helloData.getName(Locale.English) == "Hello";
helloData.getName(Locale.France) == "Bonjour";
helloData.getName(Locale.Germany) == "Hallo";
我想直接将区域设置从 URL 传递给 JsonSerializer ,以获取数据呈现的一个版本。
并且“可能”有其他版本(不仅仅是语言环境),因此不考虑继承数据混合语言环境。
【问题讨论】:
为什么不让你的 Data 类感知区域设置:引入一个 LocaleData 类,它与 Data 具有相同的字段,但翻译可翻译的内容? 嗨@@andrei-i,我在内容中回复了。谢谢。 【参考方案1】:我知道这不是一个新问题,但这是我遇到类似问题时想到的:
创建自定义注释:
@Target( ElementType.FIELD, ElementType.TYPE, ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonLocalizable
public String localizationKey();
杰克逊序列化器:
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);
注释要本地化的字段:
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;
【讨论】:
以下需要添加到自定义注解@JacksonAnnotation 中才能在createContextual 方法的BeanProperty 参数中使用。【参考方案2】:解决方案 1. 在您的 JAX-RS 实现中为 JSON 请求注册您自己的 MessageBodyWriter 实现。您的实现可能会扩展杰克逊。此外,您可能必须注销杰克逊。在MessageBodyWriter
中,您可以使用@Context
注解注入UriInfo 实例,并通过它获取任何请求参数。
解决方案 2. 更改 Data
的架构,使其能够识别区域设置。例如,创建一个 setter setLocale()
,如果设置了语言环境,它将更改返回的数据。
【讨论】:
H,DataMessageBodyWriter extends JsonSerializer implements MessageBodyWriter<Data>
看起来不错。但我必须 @Inject JacksonJsonProvider
和 @Inject Provider<ObjectMapper>
。在Provider<ObjectMapper>
的注入中,会造成循环依赖(因为ObjectMapperProvider implements Provider<ObjectMapper>
本身需要DataMessageBodyWriter
被注入)。我知道这很复杂,也许解决方案 2 更容易。
你解释的时候看起来很复杂,但我的意思更简单:直接扩展 DataMessageBodyWriter extends JacksonJsonProvider
并在调用 super 之前在扩展的 writeTo
方法中简单地添加一个 if 条件,以处理你的 Data
类型。
我使用解决方案 2。……嗯,我认为这不是最好的解决方案。因为在 JsonSerializer 中,没有从资源层获取信息的机制。在资源层时,无法分配 POJO 的输出装饰器。 (在我的例子中,装饰参数是一个语言环境)
但是您是否尝试过我的想法直接扩展 JacksonJsonProvider 以访问整个请求?以上是关于如何将参数传递给 JsonSerializer?的主要内容,如果未能解决你的问题,请参考以下文章
如何将日期对象作为第一个也是唯一的输入参数传递给 PL-SQL
如何将 POST 参数传递给 Durable Function,然后将此参数传递给 Timer Triggered 函数