日期:2014-05-16 浏览次数:20356 次
原文地址:http://kdpeterson.net/blog/2009/03/easy-json-with-jackson.html
Posted 2009-03-19.
有时候一个随意的选择可能导致一个大问题。在我们开发社交媒体产品的早期,我们决定使用JSON格式将数据存储到
HDFS中。这个想法后来被证实非常棒。它的(JSON)性能非常好,当你需要查看一个文件对象时,读取它非常方便
,而且几乎每一种语言都有对应的JSON库文件,这让你能够在你所选择的语言中轻松进行流的写入操作。
但是,我们所选择的JSON库却令我们感到不如意。net.sf.json库相对于www.json.org上的代码来说,是一个非常大
的改进,但是这个库却有轻微的内存泄露问题。这个库使用一个基于ThreadLocal中HashMap保存对象,这使得循环
检测速度更快。但是,当我们试图通过同一个Mapper对象发送GB级别的数据时,这个库的性能就会变得非常糟糕—
—因为它会保存每个反序列化对象的引用(这个特点就会导致严重的性能问题:内存泄露)。
刚开始项目时,我们对Hadoop并不熟悉,因此,我们起初并没有意识到JSON库造成了内存泄露问题。我们以为这只
是一个暂时的性能问题。因此,当内存耗尽时,我们就增加更多的内存,但是内存泄露问题却仍然存在!最后,一个
堆的转存为我们指明了正确的方向,明确方向后,就很容易找到可疑代码所在了。
发现问题原因后(json-lib库导致的),我们才做起初就应该做的事情:向邮件列表求助(邮件列表指用户反馈清单)
。我们快速预览了Hadoop核心用户所发的邮件列表,发现其中有一个人,在使用json-lib库的时候,已经遇到过和我
们相同的问题(报告这个Bug之后,json-lib迅速进行了修复)。另外还有两个人推荐使用Jaskson JSON Processor(
来做对象的JSON序列化与反序列化)。相比 json-lib,Jackson 库更好用、更简单!
下面就是一个简单的例子,展示了如何利用Jackson JSON库读写Java对象:
public class JsonUtils { private static final Log log = LogFactory.getLog(JsonUtils.class); private static final ObjectMapper mapper = new ObjectMapper(); public static String jsonFromObject(Object object) { StringWriter writer = new StringWriter(); try { mapper.writeValue(writer, object); } catch (RuntimeException e) { throw e; } catch (Exception e) { log.error("Unable to serialize to json: " + object, e); return null; } return writer.toString(); } public static User userFromJson(String json) { return (User) objectFromJson(json, User.class); } static T objectFromJson(String json, Class klass) { T object; try { object = mapper.readValue(json, klass); } catch (RuntimeException e) { log.error("Runtime exception during deserializing " + klass.getSimpleName() + " from " + StringUtils.abbreviate(json, 80)); throw e; } catch (Exception e) { log.error("Exception during deserializing " + klass.getSimpleName() + " from " + StringUtils.abbreviate(json, 80)); r