簡體   English   中英

如何使用Jersey REST序列化Java基元

[英]How to serialize Java primitives using Jersey REST

在我的應用程序中,我使用Jersey REST來序列化復雜對象。 這很好用。 但是有一些方法只返回一個int或boolean。

澤西島無法處理原始類型(據我所知),可能是因為它們沒有注釋,而澤西沒有默認注釋。 我通過創建像RestBoolean或RestInteger這樣的復雜類型來解決這個問題,它只包含一個int或boolean值並具有相應的注釋。

有沒有比編寫這些容器對象更簡單的方法?

看看Genson。它幫助了我很多類似的問題。使用Genson你可以使用int,boolean,list等泛型......這是一個簡單的例子。

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMagicList() {
    List<Object> objList = new ArrayList<>();
    stringList.add("Random String");
    stringList.add(121); //int
    stringList.add(1.22); //double
    stringList.add(false); //bolean

    return Response.status(Status.OK).entity(objList).build();
}

這將產生一個有效的JSON女巫可以像這樣非常簡單地檢索:

    Client client = Client.create();
    WebResource webResource = client.resource("...path to resource...");
    List objList = webResource.accept(MediaType.APPLICATION_JSON).get(ArrayList.class);
    for (Object obj : objList) {
        System.out.println(obj.getClass());
    }

您將看到Genson將幫助您在客戶端解碼JSON並為每個輸出正確的類。

你在寫服務還是客戶? 在服務端,你只需編寫一個MessageBodyWriter來將數據流序列化為類型的Java對象。 在我的用例中,我正在編寫的服務輸出到JSON或XML,在XML的情況下,我只是在我的類的頂部拋出一個JAXB注釋,我就完成了。

您是否看過澤西用戶指南?

3.6。 添加對新表示的支持

告訴Jersey生成適當的JSON文檔(自然json)。 我為rest app和JAXBContext解析器使用相同的類,發現它是最干凈的封裝。

更好的程序員可以實現幫助來迭代.class文件並通過識別@Annotation標簽自動列出適當的類。 我不知道如何在自己的源代碼中運行它。

這兩個鏈接有助於研究這個額外的java行話。 我不知道為什么沒有Jersey參數可以讓所有人都能開箱即用。

WEB-INF / web.xml(片段):

<servlet>
  <servlet-name>RESTServlet</servlet-name>
  <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>com.myapp.rest.RESTApplication</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>RESTServlet</servlet-name>
  <url-pattern>/servlet/rest/*</url-pattern>
</servlet-mapping>

com.myapp.rest.RESTApplication.java

package com.myapp.rest;

import java.util.*;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.ContextResolver;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;

public class RESTApplication extends Application implements ContextResolver<JAXBContext> {
    private JAXBContext context;
    private Class<?>[] types;

    public RESTApplication() throws JAXBException {
        // list JAXB bean types to be used for REST serialization
        types = new Class[] {
            com.myapp.rest.MyBean1.class, 
            com.myapp.rest.MyBean2.class, 
        };
        context = new JSONJAXBContext(JSONConfiguration.natural().build(), types);
    }

    @Override
    public Set<Class<?>> getClasses() {
        // list JAXB resource/provider/resolver classes
        Set<Class<?>> classes = new HashSet<Class<?>>();
        //for(Class<?> type : types)
        //    classes.add(type);
        classes.add(MyBeansResource.class);
        classes.add(this.getClass()); // used as a ContextResolver class
        return classes;
    }

    @Override
    public JAXBContext getContext(Class<?> objectType) {
        // this is called each time when rest path was called by remote client
        for (Class<?> type : types) {
            if (type==objectType)
                return context;
        }
        return null;
    }
}

類MyBean1,MyBean2是普通的java對象,MyBeansResource類是具有@Path rest函數的類。 他們期待標准的jaxp @Annotations在這里和那里沒有什么特別之處。 在這個java術語JSON文件之后

  • 零或單元素列表數組總是寫為json數組([]字段)
  • 原始整數和布爾字段寫為json原語(不帶引號)

我使用以下環境

  • Sun Java JDK1.6.x
  • Apache Tomcat 6.x
  • 澤西島v1.14圖書館(jersey-archive-1.14.zip)
  • webapps / myapp / WEB-INF / lib文件夾有asm-3.3.1.jar,jackson-core-asl.jar,jersey-client.jar,jersey-core.jar,jersey-json.jar,jersey-server.jar ,jersey-servlet.jar庫
  • 如果使用infomas-asl發現工具,請添加可選的annotation-detector.jar

jersey-archive.zip有較舊的asm-3.1.jar文件,可能工作正常但是chapter_deps.html鏈接到一個較新的文件。 請參閱頂部的鏈接列表。

編輯我發現了一個優秀的(快速,輕量級只有15KB)注釋發現工具。 請參閱這篇文章,了解我如何在運行時自動發現類型,並且每次添加新的java(jaxb)bean時都不再需要編輯RESTApplication。

https://github.com/rmuller/infomas-asl/issues/7

我剛剛發現用Jersey返回一個原始類型是有問題的。 我已經決定返回String。 也許這不干凈,但我認為它太臟了。 Java客戶端大多數時間由服務器的同一作者編寫,可以包裝這樣的字符串返回值並將其轉換回int。 用其他語言編寫的客戶端必須以任何方式了解返回類型。

定義RestInteger,RestBoolean可能是另一種選擇,但它更麻煩,我覺得它的吸引力太小了。

或許我在這里錯過了一些重要的東西?

實際上,最好的辦法是編寫一個自定義的ContextResolver Provider,如下所示,使用JSON的自然構建。

   @Provider
   public class YourContextResolver implements ContextResolver<JAXBContext> {

    private JAXBContext context;
    private Class<?>[] types = { YourSpecialBean.class };

    public YourContextResolver() throws Exception {
        this.context = new JSONJAXBContext(
                JSONConfiguration.natural().build(), types);
    }

    public JAXBContext getContext(Class<?> objectType) {
        for (int i = 0; i < this.types.length; i++)
            if (this.types[i].equals(objectType)) return context;

        return null;
    }
}

這里唯一需要注意的是Class []中的YourSpecialBean.class。 這定義了此提供程序將自然解析的類類型數組。

我今天遇到了同樣的問題,直到找到一個非常合適的解決方案才放棄。 我無法從1.1.5更新澤西圖書館它是一個遺留系統。 我的休息服務返回一個列表,他們應該遵循這些規則。

  1. 空列表呈現為[](幾乎不可能)
  2. 一個元素列表呈現為[](困難但僅映射配置)
  3. 許多元素列表呈現為[](簡單)

從容易到不可能開始。

3)今天沒有什么正常的JSON映射

2)注冊JAXBContextResolver,如下所示

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final JAXBContext context;
    private final Set<Class<?>> types;
    private Class<?>[] ctypes = { Pojo.class }; //your pojo class
    public JAXBContextResolver() throws Exception {
        this.types = new HashSet<Class<?>>(Arrays.asList(ctypes));
        this.context = new JSONJAXBContext(JSONConfiguration.mapped()
                .rootUnwrapping(true)
                .arrays("propertyName") //that should rendered as JSONArray even if the List only contain one element but doesn't handle the empty Collection case
                .build()
                , ctypes);
    }

    @Override
    public JAXBContext getContext(Class<?> objectType) {
        return (types.contains(objectType)) ? context : null;
    }
}

1)以下方法僅適用於Collections $ EmptyList類。 您是否可以找到一種方法,使其對所有集合都是空的。 可能代碼處理EmptyList所以。

@Provider
@Produces(value={MediaType.APPLICATION_JSON})
public class EmptyListWriter implements MessageBodyWriter<AbstractList> {

    private static final String EMPTY_JSON_ARRAY = "[]";

    @Override
    public long getSize(AbstractList list, Class<?> clazz, Type type, Annotation[] annotations, MediaType mediaType) {
        return EMPTY_JSON_ARRAY.length();
    }

    @Override
    public boolean isWriteable(Class<?> clazz, Type type, Annotation[] annotations, MediaType mediaType) {
        return clazz.getName().equals("java.util.Collections$EmptyList");
    }

    @Override
    public void writeTo(AbstractList list, Class<?> clazz, Type type, Annotation[] annotations, MediaType mediaType, 
            MultivaluedMap<String, Object> headers, OutputStream outputStream) throws IOException, WebApplicationException {
        if (list.isEmpty())
            outputStream.write(EMPTY_JSON_ARRAY.getBytes());            
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM