2016-05-20 56 views
8

我使用Jersey來實現REST風格的web服務。現在我返回數據的MediaType是JSON。自定義Json序列化器而不是Jersey的默認值?

@GET 
@Produces({MediaType.APPLICATION_JSON }) 
public Response service() { 
    return Response 
      .ok(entity) 
      .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON) 
      .build(); 
} 

這裏我設置CONTENT_TYPE以JSON和我的實體將Jersey框架轉換成JSON。

現在我想定製我的JSON響應。

例如:我想刪除空的元素或更改我的Json對象的鍵名稱。 默認新澤西州的JSON的轉換:

{ 
    "cinter" : { 
    "state" : 1, 
    "checks" : 10, 
    } 
} 

我想要什麼:

{ 
    "cin" : { 
    "st" : 1, 
    "cs" : 10, 
    } 
} 

我知道我可以根據我的使用需求傑克遜圖書館是我自己ObjectMapper定製我的JSON。

但是,如果我想以不同於Jersey的默認轉換的方式進行JSON轉換,這是否是標準方式?

或者我可以在Jersey的ObjectMapper中更改參數?

我應該使用我自己的ObjectMapper

+0

你POJO看起來像什麼?因爲它可以通過@JsonProperty(name =「cit」)等上面的字段名稱輕鬆解決。如果你不能改變你pojo,那麼是的,你必須在你的'ObjectMapper' – varren

+0

上使用自定義的Mixin或序列化程序@我的POJO有JAXB註釋(@XmlRootElement)並且我不能改變它們。所以對於每個不同的響應,我應該配置'ObjectMapper'不同?關於'ContextResolver'的任何想法? –

+0

你不能改變它們,但是你能添加註解嗎?如果可以的話,在屬性上使用'@ JsonProperty'和在類中使用'@ JsonRootName'來解決你的問題 –

回答

3

這是我對你的選擇的想法。首先

因此,對於每個不同的響應,我應該配置ObjectMapper 不同?

如果你想使用在不同的地方都JSON版本是這樣

public Response getObject()   // returns {"cinter" : {"state" : 1,"checks" : 10}} 
public Response getShortNamesObject() // returns {"cin" : {"st" : 1,"cs" : 10}} 

比是的,你必須使用多個ObjectMappers

但是,如果你只是想在所有地方都使用1個表示,那麼你可能可以使用自定義mixin爲你的類設置一次Jackson。反正這裏是你如何能做到這兩個選項:而且讓我們看一下簡單的情況下,所需要只是1 JSON版本

public class TestBean { 
    private String name; 
    private int id; 
    //getters and setters 
} 

public interface TestBeanMixin { 
    @JsonProperty("short_field_name") 
    String getName(); 
    @JsonProperty("short_field_id") 
    int getId(); 
} 

@Provider 
@Priority(1) 
public class MixInJacksonJsonProvider extends JacksonJaxbJsonProvider { 
    private static final ObjectMapper mapper = createMapper(); 

    public MixInJacksonJsonProvider() { 
     setMapper(mapper); 
    } 

    private static ObjectMapper createMapper() { 
     final ObjectMapper result = new ObjectMapper(); 
     result.addMixIn(TestBean.class, TestBeanMixin.class); 
     return result; 
    } 
} 

爲你POJO領域無處不在這段代碼將產生短名稱。並實施不同的行爲不同的要求,我們必須添加新的自定義的註釋是這樣的:

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE}) 
public @interface MixIn {} 

控制器看起來就像這樣:

@Path("test") 
public class MyResource { 

    @GET 
    @MixIn // <== Here is important part 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getShortName() { 
     return Response.ok(demoObj()).build(); 
    } 

    @POST 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response postLongName() { 
     return Response.ok(demoObj()).build(); 
    } 
} 

而且我們MixInJacksonJsonProvider將有2個@Override

//.. same as before 

    @Override 
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return super.isReadable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations); 
    } 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return super.isWriteable(type, genericType, annotations, mediaType) && hasMixInAnnotation(annotations); 
    } 
    public static boolean hasMixInAnnotation(Annotation[] annotations){ 
     for(Annotation annotation: annotations){ 
      if (annotation instanceof MixIn){ 
       return true; 
      } 
     } 
     return false; 
    } 
} 

這裏是你玩的演示代碼:https://github.com/varren/jersey2-jacksonsetup/tree/master/src/main/java/ru/varren

+0

除了短名稱之外,我還希望在某些Pojos中有像'objectMapper.WRAP_ROOT_VALUE'這樣的其他配置,可能不會其他。那麼,ObjectMapper中提供的所有配置都可以通過MixIn類中的註釋來使用嗎? –

+0

@SiddharthTrikha它真的取決於你想要什麼。如果您希望1個pojo始終具有相同的表示形式,例如WRAP_ROOT和其他pojo沒有,則可以使用1個objectmapper來完成此操作。您可以更改您的班級序列化程序或向您的班級添加註釋或使用MixIn。真的沒關係。但是如果你需要擁有多個相同POJO的json版本,那麼你必須創建多個對象映射器併爲它們使用不同的mixin/serializer +在你的控制器中使用自定義註釋來指定哪一個應該使用定製版本。 – varren

相關問題