2014-05-12 55 views
9

是否有可能使用多个配置的ObjectMappers使用杰克逊的序列化/反序列化设置泽西岛?在泽西岛使用杰克逊与多个配置的ObjectMappers

我想做什么就能做的是注册一个“默认”杰克逊ObjectMapper然后还要注册其他功能,它提供了一个ObjectMapper有一些专门配置的能力即在某些情况下将“覆盖”的“默认” ObjectMapper

例如,这ContextResolver将是 “默认” 的映射:

@Provider 
@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonMapperProvider implements ContextResolver<ObjectMapper> { 
    private final ObjectMapper mObjectMapper; 

    public JacksonMapperProvider() { 
     mObjectMapper = createMapper(); 
    } 

    protected abstract ObjectMapper createMapper() { 
     ObjectMapper mapper = createMapper(); 

     return mapper 
      .setSerializationInclusion(Include.ALWAYS) 
      .configure(JsonParser.Feature.ALLOW_COMMENTS, true) 
      .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) 
      .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) 
      .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     return mObjectMapper; 
    } 
} 

ContextResolver将覆盖 “默认” 的映射:

@Provider 
@Consumes(MediaType.APPLICATION_JSON) 
@Produces(MediaType.APPLICATION_JSON) 
public class SpecializedMapperProvider implements ContextResolver<ObjectMapper> { 
    private final ObjectMapper mObjectMapper; 

    public SpecializedMapperProvider() { 
     mObjectMapper = createMapper(); 
    } 

    protected abstract ObjectMapper createMapper() { 
     ObjectMapper mapper = createMapper(); 

     return mapper 
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 
      .setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")) 
      .registerModule(new SpecializedModule1()) 
      .registerModule(new SpecializedModule2()); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     if(SomeType.isAssignableFrom(type)) { 
      return mObjectMapper; 
     } 
     return null; 
    } 
} 

我在JacksonJsonProvider见Jackson支持ObjectMapper提供者注入/解析的代码。然而,在实践中,我所看到的是供应商的“订单”似乎是随机的(我猜测它不是,但我不能理清如何控制订单)。有时“覆盖”出现在“默认”之前,一切正常,但在下次服务器启动时,订单会发生变化。

我试图得到这个在许多方面的工作,包括:

  • 手动注册的ContextResolver<ObjectMapper>实现(在不同的顺序)
  • 通过@Provider注释
  • 指定注册的ContextResolver<ObjectMapper>实现注册时优先

我使用的是以下产品:

  • 泽西2.8
  • 杰克逊2.3.3

也许我是把一个完全不正确的方法呢?
有没有更好的方法来实现我想要做的事情? 也许我应该只定义两个独立的JAX-RS应用程序,并且每个应用程序都有一个ObjectMapper配置?

+0

我发现是什么,一旦你有'ObjectMapper defaultMapper =返回新ObjectMapper()',它与默认的'JacksonJsonProvider'实例不一样。至少不适用于'JacksonJaxbJsonProvider'。 – ulab

回答

2

您可以配置提供程序的顺序,但它实际上是最好在这种情况下使用一个供应商:

@Provider 
public class JacksonMapperProvider implements ContextResolver<ObjectMapper> { 
    private final ObjectMapper defaultMapper; 
    private final ObjectMapper specializedMapper; 

    public JacksonMapperProvider() { 
     defaultMapper = createDefaultMapper(); 
     specializedMapper = createSpecializedMapper(); 
    } 

    private static ObjectMapper createDefaultMapper() { 
     return new ObjectMapper() 
      .setSerializationInclusion(Include.ALWAYS) 
      .configure(JsonParser.Feature.ALLOW_COMMENTS, true) 
      .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) 
      .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) 
      .configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); 
    } 

    private static ObjectMapper createSpecializedMapper() { 
     return new ObjectMapper() 
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) 
      .setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS")) 
      .registerModule(new SpecializedModule1()) 
      .registerModule(new SpecializedModule2()); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> type) { 
     if (SomeType.isAssignableFrom(type)) { 
      return specializedMapper; 
     } 
     else { 
      return defaultMapper; 
     } 
    } 
} 
+2

谢谢。这是我最初做的工作,但是,我希望将应用程序的不同模块/区域分开并且不可知,并避免可能由于需要不同映射器而导致的潜在“大型提供程序”。你能否详细说明为什么“在这种情况下最好使用一个提供商”_? –

+0

我有一个类似的问题变得更糟,因为我们想为Jackson注解使用MixIns,而不是将它们放在实际的类上。我们通过创建自己的'@ JsonMixin'注释来解决我们的问题,然后在运行时扫描所有注释的对象。你可以做类似的事情动态地配置你的ObjectMapper,并且只保留一个。 – Baldy