programing

Java를 사용하여 부분 JSON 응답을 반환하려면 어떻게 해야 합니까?

sourcejob 2023. 4. 4. 21:16
반응형

Java를 사용하여 부분 JSON 응답을 반환하려면 어떻게 해야 합니까?

저는 RESTful API를 구축하고 있으며 개발자들에게 JSON 응답에서 반환할 필드를 선택할 수 있는 옵션을 제공하고 싶습니다.이 블로그 투고에서는 여러 API(Google, Facebook, Linked In)를 통해 개발자가 응답을 커스터마이즈할 수 있는 예를 보여 줍니다.이를 부분 응답이라고 합니다.

예를 들어 다음과 같습니다.

/users/123?fields=userId,fullname,title

위의 예에서 API는 사용자 "123"의 userId, fullName 및 제목 필드를 반환해야 합니다.

RESTful 웹 서비스에 이를 구현하는 방법에 대한 아이디어를 찾고 있습니다.현재 CXF(편집: 및 잭슨)를 사용하고 있습니다만, 다른 JAX-RS 실장을 시험해 보고 싶습니다.

이게 제가 현재 가지고 있는 것입니다.완전한 사용자 개체를 반환합니다.실행 시 API 호출자가 원하는 필드만 "필드" 패러메터에 따라 반환하려면 어떻게 해야 합니까?다른 필드를 Null로 만들지 않습니다.그냥 반품하고 싶지 않아요.

@GET
@Path("/{userId}")
@Produces("application/json")
public User getUser(@PathParam("userId") Long userId, 
    @DefaultValue("userId,fullname,title") @QueryParam("fields") String fields) {

User user = userService.findOne(userId);

StringTokenizer st = new StringTokenizer(fields, ",");
while (st.hasMoreTokens()) {

    // here's where i would like to select only the fields i want to return

}
return user;
}

갱신:

unludo의 링크를 팔로우하여 링크했습니다.http://wiki.fasterxml.com/JacksonFeatureJsonFilter

내가 추가한 정보로@JsonFilter("myFilter")내 도메인 클래스까지.그 후 다음과 같이 RESTful 서비스 메서드를 User가 아닌 String을 반환하도록 수정했습니다.

@GET
@Path("/{userId}")
@Produces("application/json")
public String getUser(@PathParam("userId") Long userId,
                    @DefaultValue("userId,fullname,title") @QueryParam("fields") String fields) {

    User user = userService.findOne(userId);

    StringTokenizer st = new StringTokenizer(fields, ",");
    Set<String> filterProperties = new HashSet<String>();
    while (st.hasMoreTokens()) {
        filterProperties.add(st.nextToken());
    }

    ObjectMapper mapper = new ObjectMapper();
    FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept(filterProperties));

    try {
        String json = mapper.filteredWriter(filters).writeValueAsString(user);
        return json;
    } catch (IOException e) {
        e.printStackTrace();
    return e.getMessage();
    }
}

검사를 더 해야 하는데 아직까지는 괜찮아요.

Jackson(JSON lib - Java의 표준 종류)을 사용하는 경우,@View주석을 사용하여 결과 개체에서 원하는 내용을 필터링할 수 있습니다.

역동적인 것을 원하시니 좀 더 복잡하네요.찾으시는 내용은 http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html (6 참조)를 참조해 주세요.완전 동적 필터링:@JsonFilter).

당신이 찾을 수 있는 해결책을 알고 싶습니다.

모든 요청에 대해 리소스 메서드 내에 ObjectMapper 인스턴스를 생성하면 상당한 성능 오버헤드가 발생할 수 있습니다.Jackson의 퍼포먼스 베스트 프랙티스에 따르면 오브젝트 맵은 만드는 데 비용이 많이 듭니다.

대신 Jackson 2.3 ObjectWriterModifier/ObjectReaderModifier 기능을 사용하여 리소스 메서드 내에서 JAX-RS 공급자의 잭슨 개체 작성기를 사용자 정의할 수 있습니다.

다음으로 리소스 메서드 내에서 사용되는 JAX-RS 잭슨 공급자에 적용되는 필터 세트를 변경하는 ObjectWriterModifier 스레드 로컬개체를 등록하는 예를 나타냅니다.JAX-RS 실장에 대한 코드는 테스트하지 않았습니다.

public class JacksonObjectWriterModifier2 {

    private static class FilterModifier extends ObjectWriterModifier {
        private final FilterProvider provider;

        private FilterModifier(FilterProvider provider) {
            this.provider = provider;
        }

        @Override
        public ObjectWriter modify(EndpointConfigBase<?> endpoint, MultivaluedMap<String, Object> responseHeaders,
                                   Object valueToWrite, ObjectWriter w, JsonGenerator g) throws IOException {
            return w.with(provider);
        }
    }

    @JsonFilter("filter1")
    public static class Bean {
        public final String field1;
        public final String field2;

        public Bean(String field1, String field2) {
            this.field1 = field1;
            this.field2 = field2;
        }
    }

    public static void main(String[] args) throws IOException {
        Bean b = new Bean("a", "b");
        JacksonJsonProvider provider = new JacksonJsonProvider();
        ObjectWriterInjector.set(new FilterModifier(new SimpleFilterProvider().addFilter("filter1",
                SimpleBeanPropertyFilter.filterOutAllExcept("field1"))));

        provider.writeTo(b, Bean.class, null, null, MediaType.APPLICATION_JSON_TYPE, null, System.out);
    }

}

출력:

{"field1":"a"}

Library jersey-entity-filtering은 다음과 같이 할 수 있습니다.

https://github.com/jersey/jersey/tree/2.22.2/examples/entity-filtering-selectable

https://jersey.java.net/documentation/latest/entity-filtering.html

예:

마이 오브젝트

public class Address {

    private String streetAddress;
    private String region;
    private PhoneNumber phoneNumber;
}

URL

사람/1234?select=streetAddress,지역

돌아가다

{
   "streetAddress": "2 square Tyson",
   "region": "Texas"
}

메이븐에 추가

<dependency>
    <groupId>org.glassfish.jersey.ext</groupId>
    <artifactId>jersey-entity-filtering</artifactId>
    <version>2.22.2</version>
</dependency>

언급URL : https://stackoverflow.com/questions/9314735/how-to-return-a-partial-json-response-using-java

반응형