2012-05-10 28 views
12

trong Java khi tôi sử dụng các chú thíchJax-rs JSON đầu ra khá

@Produces("application/json") 

đầu ra không được formated thành dạng có thể đọc được của con người. Làm thế nào để tôi đạt được điều đó?

+0

gì json-serializer bạn đang sử dụng? –

+0

Chỉ cần sử dụng tiêu chuẩn netbeans. Được tạo bằng thuật sĩ "Các dịch vụ Web RESTful mới từ các lớp thực thể" Tôi mới làm quen với nó, nhưng tôi nghĩ đó là jackson? – niklas

+1

Có nó là Jackson – DaTroop

Trả lời

13

Tạo lớp này ở bất cứ đâu trong dự án của bạn. Nó sẽ được tải về triển khai. Lưu ý rằng .configure(SerializationConfig.Feature.INDENT_OUTPUT, true); sẽ định cấu hình trình ánh xạ để định dạng đầu ra.

Đối Jackson 2.0 và sau, thay thế hai .configure() dòng với những: .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) .configure(SerializationFeature.INDENT_OUTPUT, true);

Và thay đổi nhập khẩu cho phù hợp.

package com.secret; 

import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.Provider; 
import org.codehaus.jackson.map.DeserializationConfig; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.SerializationConfig; 

/** 
* 
* @author secret 
*/ 
@Provider 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonContextResolver implements ContextResolver<ObjectMapper> { 
    private ObjectMapper objectMapper; 

    public JacksonContextResolver() throws Exception { 
     this.objectMapper = new ObjectMapper(); 
    this.objectMapper 
     .configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false) 
     .configure(SerializationConfig.Feature.INDENT_OUTPUT, true); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> objectType) { 
     return objectMapper; 
    } 
} 

Hãy nhớ rằng định dạng có tác động tiêu cực đến hiệu suất.

+2

Làm thế nào để Jersey biết sử dụng trình giải quyết ngữ cảnh này, thay vì nhà cung cấp JAXRS được xây dựng cho Jackson? – Cheeso

+0

với chú thích @Provider – DaTroop

+1

Có lẽ cả hai đều được chú thích theo cách đó ... – Cheeso

17

Chỉ dành cho bản ghi, nếu bạn muốn cho phép đầu ra đẹp chỉ cho một số tài nguyên bạn có thể sử dụng the @JacksonFeatures annotation trên phương pháp tài nguyên.

Dưới đây là ví dụ:

@Produces(MediaType.APPLICATION_JSON) 
@JacksonFeatures(serializationEnable = { SerializationFeature.INDENT_OUTPUT }) 
public Bean resource() { 
    return new Bean(); 
} 
+1

'@ JacksonFeatures' chỉ khả dụng trên phương thức chứ không phải lớp. – NomeN

1

Xây dựng về câu trả lời hữu ích DaTroop của, đây là một phiên bản khác mà cho phép lựa chọn giữa json tối ưu hóa và json định dạng dựa trên sự vắng mặt hay sự hiện diện của một tham số "đẹp":

package test; 


import javax.ws.rs.Produces; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.MultivaluedMap; 
import javax.ws.rs.core.UriInfo; 
import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.Provider; 

import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.SerializationConfig; 

@Provider 
@Produces(MediaType.APPLICATION_JSON) 
public class JacksonContextResolver implements ContextResolver<ObjectMapper> { 

    private ObjectMapper prettyPrintObjectMapper; 
    private UriInfo uriInfoContext; 

    public JacksonContextResolver(@Context UriInfo uriInfoContext) throws Exception { 
     this.uriInfoContext = uriInfoContext; 

     this.prettyPrintObjectMapper = new ObjectMapper(); 
     this.prettyPrintObjectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); 
    } 

    @Override 
    public ObjectMapper getContext(Class<?> objectType) { 

     try { 
      MultivaluedMap<String, String> queryParameters = uriInfoContext.getQueryParameters(); 
      if(queryParameters.containsKey("pretty")) { 
       return prettyPrintObjectMapper; 
      } 

     } catch(Exception e) { 
      // protect from invalid access to uriInfoContext.getQueryParameters() 
     } 

     return null; // use default mapper 
    } 
} 
+0

Trong khi đây là một giải pháp tốt - nó chỉ hoạt động * lần đầu tiên * một tài nguyên được gọi. Sau đó, các nhà cung cấp đã được đăng ký và bạn đang mắc kẹt với khá in (hay không). Để có sự linh hoạt thực sự, hãy chọn giải pháp Lọc. – mvreijn

12

Đây là cách bạn có thể thực hiện đúng điều kiện đầu ra khá đẹp/không xinh đẹp dựa trên sự hiện diện của "đẹp" trong chuỗi truy vấn.

Tạo một PrettyFilter mà thực hiện ContainerResponseFilter, mà sẽ được thực hiện trên mọi yêu cầu:

@Provider 
public class PrettyFilter implements ContainerResponseFilter { 

    @Override 
    public void filter(ContainerRequestContext reqCtx, ContainerResponseContext respCtx) throws IOException { 

     UriInfo uriInfo = reqCtx.getUriInfo(); 
     //log.info("prettyFilter: "+uriInfo.getPath()); 

     MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters(); 
     if(queryParameters.containsKey("pretty")) { 
      ObjectWriterInjector.set(new IndentingModifier(true)); 
     } 

    } 

    public static class IndentingModifier extends ObjectWriterModifier { 

     private final boolean indent; 

     public IndentingModifier(boolean indent) { 
      this.indent = indent; 
     } 


     @Override 
     public ObjectWriter modify(EndpointConfigBase<?> endpointConfigBase, MultivaluedMap<String, Object> multivaluedMap, Object o, ObjectWriter objectWriter, JsonGenerator jsonGenerator) throws IOException { 
      if(indent) jsonGenerator.useDefaultPrettyPrinter(); 
      return objectWriter; 
     } 
    } 
} 

Và khá nhiều đó là nó!

Bạn sẽ cần phải đảm bảo rằng lớp này được Jersey sử dụng bằng quét gói tự động hoặc được đăng ký theo cách thủ công.

Đã dành vài giờ để cố gắng đạt được điều đó và thấy rằng chưa có ai xuất bản giải pháp đã sẵn sàng sử dụng trước đây.

+0

Đây là giải pháp tốt nhất cho đến nay, tôi ước tôi có thể upvote hai lần. Đừng quên sử dụng 'register (PrettyFilter.class)' trong 'ResourceConfig' của bạn. – mvreijn

Các vấn đề liên quan