如何将参数传递给JsonSerializer?

sma*_*ufo 6 java jax-rs jsonserializer jackson dropwizard

我有一个简单的数据服务:

@GET
public Data getData(@QueryParam("id") Long id) {
  Data data = dataService.getData(id);
  return data;
}
Run Code Online (Sandbox Code Playgroud)

和匹配DataSerializer实现JsonSerializer<Data>:将DataSerializer通过注册到杰克逊:

simpleModule.addSerializer(Data.class , dataSerializer);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(simpleModule);
Run Code Online (Sandbox Code Playgroud)

它运作良好.但今天,我想添加另一个Locale参数,并希望DataSerializer输出相应的内容:

@GET
public Data getData(@QueryParam("id") Long id , @QueryParam("locale") Locale locale)
Run Code Online (Sandbox Code Playgroud)

' Data'本身包含各种语言环境变体,我希望获得指定的语言环境输出.

但是当我locale从参数中获取时,我不知道如何将locale值传递给DataSerializer...

反正有没有实现这个目标?

除了这个解决方案:

Data data = dataService.getData(id.get() , locale);
Run Code Online (Sandbox Code Playgroud)

这不是我想要的.

这似乎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";
Run Code Online (Sandbox Code Playgroud)

我想直接将语言环境从URL传递给JsonSerializer,以获得一个版本的数据表示.

并且'可能'还有其他版本(不仅仅是区域设置),因此,不考虑继承数据混合区域设置.

小智 7

我知道这不是一个新问题,但这是我面对类似问题时想到的:

  1. 创建自定义注释:

    @Target({ ElementType.FIELD, ElementType.TYPE, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface JsonLocalizable {
    
      public String localizationKey();
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  2. Jackson序列化器:

     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);
          }
        }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 注释要本地化的字段:

    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;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)


And*_*i I 2

解决方案 1.在您的 JAX-RS 实现中,为 JSON 请求注册您自己的MessageBodyWriter实现。也许你的实施会延长杰克逊的时间。此外,您可能必须取消注册杰克逊。在 a 中MessageBodyWriter,您可以使用注释注入UriInfo@Context实例,并通过它您可以获得任何请求参数。

解决方案 2.更改 的体系结构Data,使其能够识别区域设置。例如,创建一个设置器setLocale(),如果设置了语言环境,它将更改返回的数据。