问题
JSON.toJSONString(this) 出错:
com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.48, class com.biz.dao.FiniteStateMachineDAO, fieldName: finiteStateMachineDAO, write javaBean error, fastjson version 1.2.48, class com.alibaba.druid.pool.DruidDataSource, fieldName : dataSource, write javaBean error, fastjson version 1.2.48, class com.mysql.jdbc.JDBC4Connection, fieldName : connection, write javaBean error, fastjson version 1.2.48, class com.mysql.jdbc.JDBC4DatabaseMetaData, fieldName : metaData, Positioned Update not supported. at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:465) at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:120) at com.alibaba.fastjson.serializer.ASMSerializer_136_PetaDataImportHandler.write(Unknown Source) at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:281)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:673)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:611)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:576)
排查
查看本类,发现有一个数据库 DAO 字段
@Resource
private FiniteStateMachineDAO finiteStateMachineDAO;
数据库访问使用的是 hibernate,参考此文:
https://stackoverflow.com/questions/15916912/json-java-sql-sqlexception-positioned-update-not-supported
It seems like a Hibernate lazy loading problem.
If the object you want to format is some kind of hibernate model classes, and configure those classes to lazy load, this problem will happen.
The reason is that hibernate use cglib to dynamic generate this model classes(using subclass way to generate class), those sub-classes contain new attributes like "hibernateLazyInitializer". Then JSONObject will also try to serialize these new attributes. Then the exception happens.
You can try to add the following code to fix this problem:
JsonConfig cfg = new JsonConfig();
cfg.setExcludes(new String[]{"handler","hibernateLazyInitializer"});
JSONObject json = JSONObject.fromObject(obj,cfg);
解决
将 DAO 字段在 JSON serialize 中去除
/*
* 第一种:在字段前加注解。
* @JSONField(serialize=false)
* private String name;
*/
/*
* 第二种:在对字段前面加transient。
* private transient String name;
*/