jackson.databind之 com.fasterxml.jackson.databind.ser...错误

今天用springboot+themeleaf+hibernate做项目,用ajax实现前端后台交互,却意外地发现这种错误,搞了一个下午,尝试过百度的多种方法,都宣告失败,直到看到这篇文章才有所觉悟(http://www.cnblogs.com/sxdcgaq8080/p/5765392.html),这只是原因之一;

1 . 错误信息:

at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:149) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:112) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.8.jar:2.8.8]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.8.jar:2.8.8]

错因分析:

原因1:多对一映射属性混杂

原因2:response回来一个或多个连接数据库的实体类(这是最常见的错因,详细分析看最后)


这个问题多数是多对一和一对多的问题造成的,之前看过一篇文章说,在一个VO里面含有另一个VO作为属性的这个VO属性的getter()方法上面添加@JsonIgnore,如下图


这样确实是不会报上面开头的错误,但是用完ajax你会发现,有关这个被@JsonIgnore注解的属性在前端返回的是undefined,也就是说,用@JsonIgnore会造成备注解的属性数据丢失,因此,@JsonIgnore根本不是我们想要的解决方案。

请大家看一下这篇文章的作者是怎么想的(http://www.cnblogs.com/sxdcgaq8080/p/5765392.html),看完之后我有所觉悟,我发一下我之前错误时候的代码,看看你们能不能找到错误。

model---OrderdetailVO

public class OrderdetailVO {
	
	private Integer id;
	private Integer orderId;
	private Integer foodCount;
	private	Integer foodId;
	private FoodVO myFoodVO;
	private OrdersVO ordersVO;
	
	/*@JsonIgnore*/
	public FoodVO getMyFoodVO() {
		return myFoodVO;
	}
	public void setMyFoodVO(FoodVO myFoodVO) {
		this.myFoodVO = myFoodVO;
	}
	public OrderdetailVO() {
		
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	public Integer getFoodId() {
		return foodId;
	}
	public void setFoodId(Integer foodId) {
		this.foodId = foodId;
	}
	public Integer getOrderId() {
		return orderId;
	}
	public void setOrderId(Integer orderId) {
		this.orderId = orderId;
	}
	public Integer getFoodCount() {
		return foodCount;
	}
	public void setFoodCount(Integer foodCount) {
		this.foodCount = foodCount;
	}
	public OrdersVO getOrdersVO() {
		return ordersVO;
	}
	public void setOrdersVO(OrdersVO ordersVO) {
		this.ordersVO = ordersVO;
	}
}


model---FoodVO
public class FoodVO {

	private Integer foodid;
	private String foodName;       
	private FoodType foodtype;
	private double foodPrice;
	private double mprice;
	private String remark;
	private String foodimg;
	
	public FoodVO() {}
	public Integer getFoodid() {
		return foodid;
	}
	public void setFoodid(Integer foodid) {
		this.foodid = foodid;
	}
	public String getFoodName() {
		return foodName;
	}
	public void setFoodName(String foodName) {
		this.foodName = foodName;
	}
	public FoodType getFoodtype() {
		return foodtype;
	}
	public void setFoodtype(FoodType foodtype) {
		this.foodtype = foodtype;
	}
	public double getFoodPrice() {
		return foodPrice;
	}
	public void setFoodPrice(double foodPrice) {
		this.foodPrice = foodPrice;
	}
	public double getMprice() {
		return mprice;
	}
	public void setMprice(double mprice) {
		this.mprice = mprice;
	}
	public String getRemark() {
		return remark;
	}
	public void setRemark(String remark) {
		this.remark = remark;
	}
	public String getFoodimg() {
		return foodimg;
	}
	public void setFoodimg(String foodimg) {
		this.foodimg = foodimg;
	}
}

model----FoofType
@Entity
@Table(name = "foodtype")
public class FoodType implements PO {
	@Id
	@GeneratedValue
	@Column(name = "ID")
	private Integer foodTypeId;
	@OneToMany(cascade=CascadeType.ALL,mappedBy="foodtype") 
	private Set<Food> foods;
	@Column(name = "TYPENAME")
	private String foodTypeName;
	public FoodType() {}
	public Integer getFoodTypeId() {
		return foodTypeId;
	}
	public void setFoodTypeId(Integer foodTypeId) {
		this.foodTypeId = foodTypeId;
	}
	public Set<Food> getFoods() {
		return foods;
	}
	public void setFoods(Set<Food> foods) {
		this.foods = foods;
	}
	public String getFoodTypeName() {
		return foodTypeName;
	}
	public void setFoodTypeName(String foodTypeName) {
		this.foodTypeName = foodTypeName;
	}
}

ajax的js
	$(".check-order").click(function(){
		var orderId = $(this).parent().siblings().eq(0).text();
	
		var htmlString = "";
		$("#modal-content").html("");
		$.ajax({
					type:"POST",
					 dataType: "json",  
		             async: false,
					url:"/orderdetail/"+orderId,
					contentType: "application/json;charset=utf-8", 
					 data:{
						 
						},
					success:function(data){
						
						for(var i=0;i<data.length;i++){
							var orderdetailvo = data[i];
							alert(orderdetailvo.id)
							alert(orderdetailvo.myFoodVO.foodPrice);
							alert(orderdetailvo.ordersVO.totlePrice)
						
							
							/* htmlString += ' <label class="col-sm-2 control-label">';
							 htmlString +=  orderdetail.foodVO.foodname;    
							 htmlString += ' </label>';*/
							/*
							 htmlString += ' <label class="col-sm-2 control-label">';
							 htmlString +=  orderdetail.foodVO.foodname;         
							 htmlString += ' </label>';
							 
							 htmlString += ' <label class="col-sm-2 control-label">';
							 htmlString +=  orderdetail.foodVO.foodprice;         
							 htmlString += ' </label>';
							 
							 htmlString += ' <label class="col-sm-2 control-label">';
							 htmlString +=  orderdetail.FOODCOUNT;         
							 htmlString += ' </label>';
							 
							 htmlString += ' <label class="col-sm-2 control-label">';
							 htmlString +=  ((orderdetail.foodVO.foodprice) * orderdetail.FOODCOUNT);         
							 htmlString += ' </label>';*/
					 
							 
						}
					},
					 error: function(XMLHttpRequest, textStatus, errorThrown) {
						 alert("XMLHttpRequest.status:"+XMLHttpRequest.status+"\n"+"XMLHttpRequest.readyState:"+XMLHttpRequest.readyState+"\n"
								 +"textStatus:"+textStatus);

						   }
				})
		$("#modal-content").html(htmlString);
	
		$("#orderDetail").modal("show");
	})


控制器:

@ResponseBody
	@RequestMapping(value = "/orderdetail/{orderId}", method = RequestMethod.POST)
	public List<OrderdetailVO> orderdetail(Model model, @PathVariable Integer orderId) {

		List<OrderdetailVO> orderdetailVOList = new ArrayList<OrderdetailVO>();
		List<Orderdetail> list = orderdetailDAO.getDetailByOrderId(orderId);
		for (Orderdetail od : list) {
			FoodVO foodVO = new FoodVO();
			OrdersVO ordersVO = new OrdersVO();
			OrderdetailVO vo = new OrderdetailVO();

			BeanUtils.copyProperties(od.getFood(), foodVO);
			BeanUtils.copyProperties(od.getOrders(), ordersVO);
			// foodVO.setFoodtype(od.getFood().getFoodtype().getFoodTypeId());
			vo.setId(od.getId());
			vo.setFoodId(od.getFood().getFoodid());
			vo.setFoodCount(od.getFoodCount());
			vo.setOrderId(od.getOrders().getId());
			vo.setMyFoodVO(foodVO);  //通过调试知道是卡在这里出现最上面的错误信息,
			                         //到这里,你再看看上面的model之间的联系,知道为什么死循环了吗?
			vo.setOrdersVO(ordersVO);
			orderdetailVOList.add(vo);
		}

		for (OrderdetailVO vo : orderdetailVOList) {
			System.out.println();
			System.out.println("==============================");
			System.out.println("detailId:" + vo.getId());
			System.out.println("foodcount:" + vo.getFoodCount());
			System.out.println("foodId" + vo.getMyFoodVO().getFoodid());
			System.out.println("foodname" + vo.getMyFoodVO().getFoodName());
			System.out.println("foodprice" + vo.getMyFoodVO().getFoodPrice());
			System.out.println("orderId" + vo.getOrdersVO().getId());
			System.out.println("==============================");
			System.out.println();
		}

		if (orderdetailVOList.isEmpty()) {
			return null;
		}
		return orderdetailVOList;
	}


我的死循环分析:在上面重点提到的vo.setMyFoodVO(foodVO); 那里,foodVO通过BeanUtils复制对象,看似没问题,但再看看FoodVO里面有什么属性?其中有一个private FoodType foodtype;属性,FoodType 类里面有一个private Set<Food> foods;于是就像推荐文章中所说你中有我,我中有你,造成死循环,直到内存溢出。

解决:在VO删除不必要的属性或者改属性类型,避免vo之间互相调用,造成死循环。

出现错误,首先要定位到编译器出错位点,使用打印方式也可以,看看编译器走到哪里才会报错,找到报错的那一行,重点查看分析该代码存在的隐患或错误,深入分析该代码及其附属代码,逐步分析打印,直到找到最终结果。



原因2:返回连接数据库的实体类导致此错误,当然前提是ajax数据类型以及同步等等确保没错,ajax参数如下:

正确的ajax示例:


$.ajax({
			type:"POST",
			dataType:"json",
			url:url,  //后台url请求,处理传递的参数
			async: false,
			 data:{
				},
			success:function(data){
			//ajax请求成功执行该函数
			},
			 error: function(XMLHttpRequest, textStatus, errorThrown) {
				 alert("XMLHttpRequest.status:"+XMLHttpRequest.status+"\n"+"XMLHttpRequest.readyState:"+XMLHttpRequest.readyState+"\n"
						 +"textStatus:"+textStatus);

				   }
		});
		


原本报错时候的控制器代码:



解决方案:(map里面放VO对象返回)


解析:由于先前map里面放的是连接数据库的实体类,故而报此错误,现在OrdersVO对象含有Orders对象的所有属性,但没有连接数据库,至于BeanUtils,这是spring自带的方法,用于在两个对象之间属性相同的字段进行复制值,不懂可以百度,现在返回的是VO的List,错误解决;




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值