[英]Using Jackson2 with Spring 4.0 (MVC + REST+ Hibernate)
我正在制作一個安靜的應用程序並嘗試將對象列表轉換為json以獲取特定的URL(@RequestMapping / @ResponseBody)
我的classpath中有jackson-hibernate4和jackson-core,databind等。
這是我想要轉換為json的對象。
@Entity
@Table(name="Product")
public class Product {
@Id
@Column(name="productId")
@GeneratedValue
protected int productId;
@Column(name="Product_Name")
protected String name;
@Column(name="price")
protected BigDecimal baseprice;
@OneToMany(cascade = javax.persistence.CascadeType.ALL,mappedBy="product",fetch=FetchType.EAGER)
protected List<ProductOption> productoption = new ArrayList<ProductOption>();
@OneToMany(cascade = javax.persistence.CascadeType.ALL,mappedBy="product",fetch=FetchType.EAGER)
protected List<ProductSubOption> productSubOption = new ArrayList<ProductSubOption>();
@ManyToOne
@JoinColumn(name="ofVendor")
protected Vendor vendor;
Product里面的兩個對象也是POJO'S ..
這是我檢索產品列表的方法
@Override
public List<Product> getMenuForVendor(int vendorId) {
List<Product> result = em.createQuery("from "+Product.class.getName()+" where ofVendor = :vendorId").setParameter("vendorId", vendorId).getResultList();
System.out.println(result.size());
return result;
}
當我嘗試在我的控制器中返回此列表時,我得到了“不能懶惰加載json”所以我設置我的對象急切地獲取。 這是我的控制器
@Autowired
private MenuDaoImpl ms;
@RequestMapping(value = "/{vendorId}", method = RequestMethod.GET)
public @ResponseBody List<Product> getMenu(@PathVariable int vendorId){
List<Product> Menu = Collections.unmodifiableList(ms.getMenuForVendor(vendorId));
return Menu;
}
現在,當我點擊我的網址localhost:8080 / getMenu / 1我應該顯示一個json字符串,但我得到一個很大的錯誤列表
WARN : org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver - Handling of [org.springframework.http.converter.HttpMessageNotWritableException] resulted in Exception
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:467)
Could not write JSON: Infinite recursion (StackOverflowError) (through reference chain:
我不確定我是否遺漏了任何東西。 請指導。
我使用@JsonBackReference解決了@ManyToOne綁定和@OneToMany綁定的@JsonManagedReference。
謝謝“Sotirios Delimanolis”
問題已經得到解答。 我只是把一個很好的例子的鏈接清楚地解釋了問題和解決方案。 http://geekabyte.blogspot.in/2013/09/fixing-converterhttpmessagenotwritablee.html
我意識到這可能不是100%你所追求的,但從來沒有那么少,我覺得分享它,因為我花了很多時間來回應這個問題。
此外,您可以考慮使用自定義Json解析器,而不是使用Json注釋。 確保使用Jackson jar的正確包裝,因為他們最近改變了他們的包裝結構(當你使用其中任何一個數字為2的類時,如下所示)。
首先創建一個HttpMessageConverter:
@Bean
public HttpMessageConverter jacksonMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setPrefixJson(false);
converter.setPrettyPrint(true);
converter.setObjectMapper(objectMapper());
return converter;
}
添加一個ObjectMapper,您可以在其中附加映射模塊並附加您將使用的序列化程序。
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
SimpleModule module = new SimpleModule("jacksonJsonMapper", Version.unknownVersion());
module.addSerializer(Product.class, new Product());
objectMapper.registerModule(module);
return objectMapper;
}
現在創建一個序列化器。 這個類將提供你在獲取對象時看到的輸出,傑克遜將完成其余的工作。 你只需提供它應該如何看的骨架。
public class Product erializer extends JsonSerializer<Product> {
@Override
public void serialize(Product product, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if(product == null) {
//Handle it, if you want
}
if(product != null) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("id", productId.getId().toString());
jsonGenerator.writeStringField("title", product.getName());
jsonGenerator.writeStringField("basePrice", product.getBasePrice());
//Add items to the json array representation
jsonGenerator.writeArrayFieldStart("productoptions");
for(ProductOption productOption: product.getProductoption()) {
jsonGenerator.writeStartObject("field", productOption.getFoo());
jsonGenerator.writeEndObject();
}
jsonGenerator.writeEndArray();
jsonGenerator.writeEndObject();
}
}
}
在旁注中,但我仍然希望它有用:您需要確保在懶惰地獲取實體時有可用的事務。 你還應該記住,懶惰是加載實體的首選方式,除非你想在每次獲取任何引用時徹底粉碎你的服務器。
嘗試通過在其上添加@Transactional來更改獲取數據的方法,以確保在其運行時為該方法打開事務,如果不是,則在您嘗試獲取子對象時可能會關閉該事務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.