sourcecode

Jersey: 요소가 1개인 Json 배열이 개체로 직렬화됩니다.

copyscript 2023. 9. 1. 21:14
반응형

Jersey: 요소가 1개인 Json 배열이 개체로 직렬화됩니다.

Jersey/Java로 REST 서버를 만들고 있는데 이상한 동작을 발견했습니다.

서버에 객체 배열을 Json으로 반환하는 메서드가 있습니다.

@GET
@Path("/files")
@Produces(MediaType.APPLICATION_JSON)
public Object getFiles() throws Exception{
    DatabaseManager db = new DatabaseManager();
    FileInfo[] result = db.getFiles();
    return result;
}

코드가 올바르게 실행되고 데이터가 클라이언트로 반환됩니다(jQuery ajax 호출).문제는 "result" 배열에 하나 이상의 요소가 있을 경우 반환되는 데이터의 형식이 변경된다는 것입니다.

하나의 요소로 반응:

{"fileInfo":{"fileName":"weather.arff","id":"10"}}

두 가지 요소를 사용한 반응:

{"fileInfo":[{"fileName":"weather.arff","id":"10"},{"fileName":"supermarket.arff","id":"11"}]}

보시다시피 첫 번째 시나리오에서는 반환된 개체의 "fileInfo" 속성 값이 개체이고 두 번째 시나리오에서는 값이 배열입니다.내가 뭘 잘못하고 있는 거지?첫 번째 사례는 다음과 같은 것을 반환해야 하지 않습니까?

{"fileInfo":[{"fileName":"weather.arff","id":"10"}]}

즉, 내부에 단일 개체가 있는 배열입니까?

클라이언트 쪽에서 이것을 감지할 수 있다는 것은 알지만, 매우 추악한 해킹인 것 같습니다.

시간 내주셔서 감사합니다.

Jersey 공식 문서(http://jersey.java.net/nonav/documentation/latest/user-guide.html#json.pojo.approach.section) 에도 나와 있는 Jackson을 사용하게 되었습니다.

이전에 시도해 본 적이 있지만 프로젝트의 빌드 경로에 잭슨 병이 없어서 작동하지 않았습니다(문서에 따르면 저지의 핵심 라이브러리에 내장되어 있다고 생각했습니다).

방금 jackson-all.jar 파일(http://wiki.fasterxml.com/JacksonDownload) 을 추가하고 구성에서 POJO 지원을 활성화했습니다.

    <init-param>
          <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
          <param-value>true</param-value>
    </init-param>

그리고 voila!

JAXB를 사용하여 JSON 결과를 작성한 경우 Jersey JSON 프로세서를 구성하여 더 중요한 JSON 형식을 얻을 수 있습니다.

저지 공식 문서에는 상세 구성이 있습니다.

JSON 형식을 보다 중요하게 변경하려면 Jersey JSON 프로세서 자체를 구성해야 합니다.JSONConfiguration 인스턴스에 다양한 구성 옵션을 설정할 수 있습니다.그런 다음 인스턴스를 추가로 사용하여 이 영역에서 기본 구성 지점 역할을 하는 JSONConfiguredJAXB 컨텍스트를 만들 수 있습니다.전문 JSONJAXB 컨텍스트를 Jersey에 전달하려면 JAXB 컨텍스트 컨텍스트 해결기를 마지막으로 구현해야 합니다.

    @Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final JAXBContext context;
    private final Set<Class> types;
    private Class[] ctypes = { FileInfo.class}; //your pojo class
    public JAXBContextResolver() throws Exception {
        this.types = new HashSet(Arrays.asList(ctypes));
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(),
                ctypes); //json configuration
    }

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

또한 다음 답변을 통해 해결할 수 있습니다.

JAXB 개체 목록의 직렬화를 JSON으로 사용자 지정하려면 어떻게 해야 합니까?

나는 cxf를 사용하고 있습니다. 여기 JSON에서 배열을 강제로 적용하는 애플리케이션 Context.xml이 있습니다.

<jaxrs:server id="myService" serviceName="MyService"
address="/mysvc">
<jaxrs:serviceBeans>
    <ref bean="myServiceImpl"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
    <bean class="org.apache.cxf.jaxrs.provider.json.JSONProvider">
   <property name="dropRootElement" value="true" />
   <property name="supportUnwrapped" value="true" />
   <property name="namespaceMap">
      <map>
        <entry key="http://example.com/myservice" value=""/>
      </map>
   </property>
   <property name="arrayKeys">
      <list>
    <value>fileInfo</value>
      </list>
   </property>                          
    </bean>
</jaxrs:providers>
</jaxrs:server>

Jettison(Jersey와 함께)을 사용하여 사용하고 싶은 구조를 준비할 수 있습니다.JSONObject그리고.JSONArray반환 값으로.그것들은 패키지 안에 있습니다.org.codehaus.jettison.jsonjettison-1.3.2.jar의 전이적 의존성입니다.jerysey-json

겐슨 도서관 http://code.google.com/p/genson/ 도 이용할 수 있습니다.그것은 저지와 잘 통합됩니다. 단지 당신의 수업 경로에 항아리를 떨어뜨리면 모든 것이 작동할 것이 작동할 것입니다.코드를 추가로 작성할 필요가 없습니다. 지금처럼 작동해야 하지만 이상한 결과는 없습니다.

저는 꽤 많은 어려움을 겪었고 이 간단한 해결책을 찾았습니다.

pom.xml에서:

<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-jaxrs</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-xc</artifactId>
    <version>1.9.13</version>
</dependency>

web.xml에서 다음을 수행합니다.

<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.other-packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>

여기서는 어레이를 어레이 목록으로 변환하는 것으로 충분합니다.비슷한 종류의 모순된 문제가 있었습니다. 단일 요소의 경우 목록 대신 Json Array Object를 반환해야 했습니다.

거기서 나는 내 일을 끝내기 위해 아래 주석의 도움을 받았습니다.

@JsonFormat(=JsonFormat 포함).특징.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED).다음은 JSON Pojo 클래스의 예입니다.

import java.util.List;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonIgnoreProperties(ignoreUnknown = true)
public class TAResponseMapper {

    @JsonProperty("Response")
    @JsonFormat(with = JsonFormat.Feature.WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED) 
    private List<TAResponse> responses;

    public List<TAResponse> getResponses() {
        return responses;
    }

    public void setResponses(List<TAResponse> responses) {
        this.responses = responses;
    }

}

언급URL : https://stackoverflow.com/questions/13575280/jersey-json-array-with-1-element-is-serialized-as-object

반응형