Jackson处理json的一些常见使用.docx
- 文档编号:9674520
- 上传时间:2023-05-20
- 格式:DOCX
- 页数:13
- 大小:18.05KB
Jackson处理json的一些常见使用.docx
《Jackson处理json的一些常见使用.docx》由会员分享,可在线阅读,更多相关《Jackson处理json的一些常见使用.docx(13页珍藏版)》请在冰点文库上搜索。
Jackson处理json的一些常见使用
Jackson处理json的一些常见使用
2013/11/18juluren
Jackson是一个功能强大的Java串行化库。
除了支持常用的json,同时还支持Smile,BSON,XML,CSV,YAML。
接下来就介绍一些处理json时常见的使用场景,文中的例子都是在1.9版本下运行的。
Jackson的json库提供了3种API:
∙StreamingAPI:
性能最好
∙TreeModel:
最灵活
∙DataBinding:
最方便
其中最常用到的就是DataBinding了,基本的用法如下
ObjectMappermapper=newObjectMapper();
Stringjson=mapper.writeValueAsString(foo);
Foofoo=mapper.readValue(json,Foo.class);
ObjectMapper是线程安全的,应该尽量的重用。
需要注意的是,Jackson是基于JavaBean来串行化属性的,如果属性没有GETTER方法,默认是不会输出该属性的。
但是在串行化的时候,经常会有特殊的需求来对输出的结果进行自定义。
比如不输出某几个属性,或者自定义属性的名字,等等。
Jackson提供了非常多的方法来满足我们的自定义需求。
假设有这么一个对象:
classUser{
privatelongid;
privateStringname;
privateStringavator240;
privateStringavator160;
privateStringaddress;
publiclonggetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicStringgetAvator240(){
returnavator240;
}
publicStringgetAvator160(){
returnavator160;
}
publicStringgetAddress(){
returnaddress;
}
}
如果不想输出id,最简单的方法,就是给该属性加上注解JsonIgnore:
@JsonIgnore
privatelongid;
或者
@JsonIgnore
publiclonggetId(){
returnid;
}
因为JsonIgnore的target可以是CONSTRUCTOR,FIELD,METHOD
如果不想输出多个属性,比如id,address和avator160,除了在每个属性上添加JsonIgnore,也可以直接在类上添加注解JsonIgnoreProperties:
@JsonIgnoreProperties({"id","avator160","address"})
classUser{
这里的User类只有5个属性,使用annotation控制忽略哪些属性还是绰绰有余的。
加入有一个类有上百个属性,如果只想输出其中的10来个属性,使用JsonIgnore就显得太繁琐了。
此时就可以使用JSONView或MixInAnnotation了。
先来看一下JSONView,和数据库的view一样,可以为一个对象创建view,输出时只会输出view中定义的那些属性。
特别的,一个对象可以定义任意多个view,同时view也是可以继承的。
先来看看如何使用view来过滤id,address和avator160:
publicclassJsonViewDemo{
privatestaticclassUser{
privatelongid;
@JsonView({FilterView.Output.class})
privateStringname;
@JsonView({FilterView.Output.class})
privateStringavator240;
privateStringavator160;
privateStringaddress;
publiclonggetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicStringgetAvator240(){
returnavator240;
}
publicStringgetAvator160(){
returnavator160;
}
publicStringgetAddress(){
returnaddress;
}
}
privatestaticclassFilterView{
staticclassOutput{}
}
publicstaticvoidmain(String[]args)throwsException{
Useruser=newUser();
user.id=1000L;
user.name="testname";
user.avator240="240.jpg";
user.avator160="160.jpg";
user.address="someaddress";
ObjectMappermapper=newObjectMapper();
mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION,false);
System.out.println(mapper.writerWithView(FilterView.Output.class).writeValueAsString(user));
}
}
首先需要定义一个需要输出的属性的View:
FilterView.Output,然后在需要输出属性上声明该View,之后使用writerWithView(FilterView.Output.class)来串行化就可以了。
需要注意的是,在这里需要把DEFAULT_VIEW_INCLUSION设置为false,因为默认是会输出没有JsonView注解的属性的。
其实View的作用远不止如此,再来看一个更实用的例子:
假设现有个API接口,需要针对不同的客户端(ios,android)输出不同的属性,通过创建多个View就能轻松完成。
publicclassJsonApiViewDemo{
privatestaticclassUser{
privatelongid;
@JsonView({ApiView.Default.class})
privateStringname;
@JsonView({ApiView.Ios.class})
privateStringavator240;
@JsonView({ApiView.Android.class})
privateStringavator160;
privateStringaddress;
publiclonggetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicStringgetAddress(){
returnaddress;
}
publicStringgetAvator240(){
returnavator240;
}
publicStringgetAvator160(){
returnavator160;
}
}
privatestaticclassApiView{
staticclassDefault{}
staticclassIosextendsDefault{}
staticclassAndroidextendsDefault{}
}
publicstaticvoidmain(String[]args)throwsException{
ObjectMappermapper=newObjectMapper();
mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION,false);
Useruser=newUser();
user.id=10000L;
user.name="testname";
user.avator240="240.jpg";
user.avator160="160.jpg";
user.address="someaddress";
StringapiViewJson=mapper.writerWithView(ApiView.Default.class).writeValueAsString(user);
StringiosViewJson=mapper.writerWithView(ApiView.Ios.class).writeValueAsString(user);
StringandroidViewJson=mapper.writerWithView(ApiView.Android.class).writeValueAsString(user);
System.out.println(apiViewJson);
System.out.println(iosViewJson);
System.out.println(androidViewJson);
}
}
使用ApiView.Ios只会输出name和avator240。
使用ApiView.Android只会输出name和avator160。
但是,以上的所有方法都有一个缺点,那就是需要修改源代码,它们都需要在要输出的类上加上annotation。
假设没有那些要串行化的类的源代码,甚至那些类都不符合JavaBean规范,又该怎么办呢?
此时就可以使用MixInAnnotation了,其实和View差不多,也相当于是为要串行化的对象定义了一个View。
publicclassJsonMixInDemo{
staticclassUser{
privatelongid;
privateStringname;
privateStringavator240;
privateStringavator160;
privateStringaddress;
publiclonggetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicStringgetAddress(){
returnaddress;
}
}
abstractclassMixIn{
@JsonIgnoreabstractintgetAddress();
@JsonIgnorelongid;
@JsonProperty("custom_name")abstractStringgetName();
@JsonProperty("avator")Stringavator240;
}
publicstaticvoidmain(String[]args)throwsException{
ObjectMappermapper=newObjectMapper();
Useruser=newUser();
user.id=1234567L;
user.name="testname";
user.avator240="240.jpg";
user.avator160="160.jpg";
user.address="someaddress";
mapper.getSerializationConfig().addMixInAnnotations(User.class,MixIn.class);
Stringjson=mapper.writeValueAsString(user);
System.out.println(json);
}
}
将输出
{"custom_name":
"testname","avator":
"240.jpg"}
其中关键在于MixIn这个类,MixIn也可以定义成接口。
在这里,既可以过滤属性/方法,也可以定义哪些属性/方法会被输出,顺便还可以自定义输出的属性名。
在串行化前只要配置一下
addMixInAnnotations(User.class,MixIn.class)
就可以在完全不修改该类的情况下自定义输出了。
MixInAnnotation应该能满足几乎所有需要对属性进行自定义的情况了,但是MixInAnnotation的配置是静态的,不能在运行时修改。
结合JSONFilter和Mixin就可以实现动态的过滤属性了
publicclassJsonFilterDemo{
privatestaticclassUser{
privatelongid;
privateStringname;
privateStringavator240;
privateStringavator160;
privateStringaddress;
publicStringgetName(){
returnname;
}
publicStringgetAddress(){
returnaddress;
}
publicStringgetAvator240(){
returnavator240;
}
publicStringgetAvator160(){
returnavator160;
}
publiclonggetId(){
returnid;
}
}
@JsonFilter("userFilter")
privatestaticinterfaceUserFilterMixIn
{
}
publicstaticvoidmain(String[]args)throwsException{
ObjectMappermapper=newObjectMapper();
Useruser=newUser();
user.id=1000L;
user.name="testname";
user.avator240="240.jpg";
user.avator160="160.jpg";
user.address="someaddress";
FilterProvideridFilterProvider=newSimpleFilterProvider().addFilter("userFilter",SimpleBeanPropertyFilter.filterOutAllExcept(newString[]{"name","avator240"}));
mapper.setFilters(idFilterProvider);
mapper.getSerializationConfig().addMixInAnnotations(User.class,UserFilterMixIn.class);
StringuserFilterJson=mapper.writeValueAsString(user);
System.out.println(userFilterJson);
}
}
前面介绍了很多自定义输出属性的方法,如果需要在串行化时修改值,要怎么办呢?
只要实现自己的JsonSerializer就可以了,下面这个例子就会输出id的md5值
publicclassJsonCustomSerializerDemo{
staticclassUser{
@JsonSerialize(using=Md5IdSerializer.class)
privatelongid;
privateStringname;
privateStringaddress;
publiclonggetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicStringgetAddress(){
returnaddress;
}
}
publicstaticclassMd5IdSerializerextendsJsonSerializer
{
publicvoidserialize(Longvalue,JsonGeneratorgenerator,SerializerProviderprovider)
throwsIOException,JsonProcessingException{
generator.writeString(md5(value));
}
privateStringmd5(Longvalue){
returnvalue+"-md5-mock";
}
}
publicstaticvoidmain(String[]args)throwsException{
ObjectMappermapper=newObjectMapper();
Useruser=newUser();
user.id=1234567L;
user.name="testname";
user.address="someaddress";
Stringjson=mapper.writeValueAsString(user);
System.out.println(json);
}
}
接下来看一下反串行化,现在很多网站都开放了api接口,支持json格式的返回。
比如在调用了某个api后,需要解析返回的json数据获取信息,这种情况下为json创建一个对应的类是很不方便的。
此时使用TreeModel来解析json就比较方便了,下面这段代码就是用来解析人人网的用户信息的
JsonNoderoot=mapper.readTree(rerenjson);
JsonNodeuser=root.get("user");
Stringid=user.get("id").asText();
Stringname=user.get("name").asText();
JsonNodeavators=user.get("avatar");
if(avators.isArray()){
for(Iterator
it=avators.getElements();it.hasNext();){
JsonNodeavator=it.next();
if("tiny".equals(avator.get("type").asText())){
Stringava=avator.get("url").asText();
break;
}
}
}
最后列一些使用Jackson的最佳实践:
∙重用重量级对象:
ObjectMapper,JsonFactory
∙串行化性能(从高到低):
OutputStream>Writer>writeValueAsString
∙反串行化性能(从高到低):
byte[]>InputStream>Reader
∙用更轻量ObjectReader/ObjectWriter替代ObjectMapper
∙及时关闭JsonParser,JsonGenerator
上面这些tips都摘自
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Jackson 处理 json 一些 常见 使用