接下来就介绍一些处理json时常见的使用场景,文中的例子都是在1.9版本下运行的。
Jackson的json库提供了3种API:
- Streaming API : 性能最好
- Tree Model : 最灵活
- Data Binding : 最方便
其中最常用到的就是Data Binding了,基本的用法如下
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(foo);
Foo foo = mapper.readValue(json, Foo.class);
ObjectMapper是线程安全的,应该尽量的重用。
需要注意的是,Jackson是基于JavaBean来串行化属性的,如果属性没有GETTER方法,默认是不会输出该属性的。
但是在串行化的时候,经常会有特殊的需求来对输出的结果进行自定义。
比如不输出某几个属性,或者自定义属性的名字,等等。
Jackson提供了非常多的方法来满足我们的自定义需求。
假设有这么一个对象:
class User {
private long id;
private String name;
private String avator240;
private String avator160;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAvator240() {
return avator240;
}
public String getAvator160() {
return avator160;
}
public String getAddress() {
return address;
}
}
如果不想输出id
,最简单的方法,就是给该属性加上注解JsonIgnore
:
@JsonIgnore
private long id;
或者
@JsonIgnore
public long getId() {
return id;
}
因为JsonIgnore
的target可以是CONSTRUCTOR, FIELD, METHOD
如果不想输出多个属性,比如id
,address
和avator160
,除了在每个属性上添加JsonIgnore
,也可以直接在类上添加注解JsonIgnoreProperties
:
@JsonIgnoreProperties({"id","avator160","address"})
class User {
这里的User
类只有5个属性,使用annotation控制忽略哪些属性还是绰绰有余的。
加入有一个类有上百个属性,如果只想输出其中的10来个属性,使用JsonIgnore
就显得太繁琐了。
此时就可以使用JSON View或MixIn Annotation了。
先来看一下JSON View,和数据库的view一样,可以为一个对象创建view,输出时只会输出view中定义的那些属性。 特别的,一个对象可以定义任意多个view,同时view也是可以继承的。
先来看看如何使用view来过滤id
,address
和avator160
:
public class JsonViewDemo {
private static class User {
private long id;
@JsonView({FilterView.Output.class})
private String name;
@JsonView({FilterView.Output.class})
private String avator240;
private String avator160;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAvator240() {
return avator240;
}
public String getAvator160() {
return avator160;
}
public String getAddress() {
return address;
}
}
private static class FilterView {
static class Output {}
}
public static void main(String[] args) throws Exception {
User user = new User();
user.id = 1000L;
user.name = "test name";
user.avator240 = "240.jpg";
user.avator160 = "160.jpg";
user.address = "some address";
ObjectMapper mapper = new ObjectMapper();
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就能轻松完成。
public class JsonApiViewDemo {
private static class User {
private long id;
@JsonView({ApiView.Default.class})
private String name;
@JsonView({ApiView.Ios.class})
private String avator240;
@JsonView({ApiView.Android.class})
private String avator160;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String getAvator240() {
return avator240;
}
public String getAvator160() {
return avator160;
}
}
private static class ApiView {
static class Default {}
static class Ios extends Default {}
static class Android extends Default {}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false);
User user = new User();
user.id = 10000L;
user.name = "test name";
user.avator240 = "240.jpg";
user.avator160 = "160.jpg";
user.address = "some address";
String apiViewJson = mapper.writerWithView(ApiView.Default.class).writeValueAsString(user);
String iosViewJson = mapper.writerWithView(ApiView.Ios.class).writeValueAsString(user);
String androidViewJson = 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规范,又该怎么办呢? 此时就可以使用MixIn Annotation了,其实和View差不多,也相当于是为要串行化的对象定义了一个View。
public class JsonMixInDemo {
static class User {
private long id;
private String name;
private String avator240;
private String avator160;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
abstract class MixIn {
@JsonIgnore abstract int getAddress();
@JsonIgnore long id;
@JsonProperty("custom_name") abstract String getName();
@JsonProperty("avator") String avator240;
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.id = 1234567L;
user.name = "test name";
user.avator240 = "240.jpg";
user.avator160 = "160.jpg";
user.address = "some address";
mapper.getSerializationConfig().addMixInAnnotations(User.class, MixIn.class);
String json = mapper.writeValueAsString(user);
System.out.println(json);
}
}
将输出
{"custom_name":"test name","avator":"240.jpg"}
其中关键在于MixIn这个类,MixIn也可以定义成接口。
在这里,既可以过滤属性/方法,也可以定义哪些属性/方法会被输出,顺便还可以自定义输出的属性名。
在串行化前只要配置一下
addMixInAnnotations(User.class, MixIn.class)
就可以在完全不修改该类的情况下自定义输出了。
MixIn Annotation应该能满足几乎所有需要对属性进行自定义的情况了,但是MixIn Annotation的配置是静态的,不能在运行时修改。
结合JSON Filter和Mixin就可以实现动态的过滤属性了
public class JsonFilterDemo {
private static class User {
private long id;
private String name;
private String avator240;
private String avator160;
private String address;
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public String getAvator240() {
return avator240;
}
public String getAvator160() {
return avator160;
}
public long getId() {
return id;
}
}
@JsonFilter("userFilter")
private static interface UserFilterMixIn
{
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.id = 1000L;
user.name = "test name";
user.avator240 = "240.jpg";
user.avator160 = "160.jpg";
user.address = "some address";
FilterProvider idFilterProvider = new SimpleFilterProvider().addFilter("userFilter", SimpleBeanPropertyFilter.filterOutAllExcept(new String[]{"name", "avator240"}));
mapper.setFilters(idFilterProvider);
mapper.getSerializationConfig().addMixInAnnotations(User.class, UserFilterMixIn.class);
String userFilterJson = mapper.writeValueAsString(user);
System.out.println(userFilterJson);
}
}
前面介绍了很多自定义输出属性的方法,如果需要在串行化时修改值,要怎么办呢?
只要实现自己的JsonSerializer
就可以了,下面这个例子就会输出id的md5值
public class JsonCustomSerializerDemo {
static class User {
@JsonSerialize(using = Md5IdSerializer.class)
private long id;
private String name;
private String address;
public long getId() {
return id;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
public static class Md5IdSerializer extends JsonSerializer
{
public void serialize(Long value, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException {
generator.writeString(md5(value));
}
private String md5(Long value) {
return value + "-md5-mock";
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
User user = new User();
user.id = 1234567L;
user.name = "test name";
user.address = "some address";
String json = mapper.writeValueAsString(user);
System.out.println(json);
}
}
接下来看一下反串行化,现在很多网站都开放了api接口,支持json格式的返回。
比如在调用了某个api后,需要解析返回的json数据获取信息,这种情况下为json创建一个对应的类是很不方便的。
此时使用Tree Model来解析json就比较方便了,下面这段代码就是用来解析人人网的用户信息的
JsonNode root = mapper.readTree(rerenjson);
JsonNode user = root.get("user");
String id = user.get("id").asText();
String name = user.get("name").asText();
JsonNode avators = user.get("avatar");
if (avators.isArray()) {
for (Iterator
it = avators.getElements(); it.hasNext(); ){
JsonNode avator = it.next();
if ("tiny".equals(avator.get("type").asText())) {
String ava = avator.get("url").asText();
break;
}
}
}
最后列一些使用Jackson的最佳实践:
- 重用重量级对象: ObjectMapper, JsonFactory
- 串行化性能(从高到低): OutputStream > Writer > writeValueAsString
- 反串行化性能(从高到低): byte[] > InputStream > Reader
- 用更轻量ObjectReader/ObjectWriter替代ObjectMapper
- 及时关闭JsonParser, JsonGenerator
上面这些tips都摘自https://github.com/FasterXML/jackson-docs/wiki/Presentation:-Jackson-Performance,上面还有更多tips。
相关推荐
在本文中,我们将深入探讨JSONModel的使用,包括其基本用法、优点、常见问题及解决策略。 首先,让我们了解JSONModel的基本用法。要使用JSONModel,你需要在你的类中继承自JSONModel,并定义相应的属性。这些属性...
在C#开发中,处理JSON数据是常见的任务,而Newtonsoft.Json(也称为Json.NET)是一个广泛使用的库,它提供了强大的JSON序列化和反序列化功能。本文将详细介绍如何使用Newtonsoft.Json进行JSON操作,包括数据结构的...
7. JSON高级用法:如使用JSON Schema验证JSON数据结构,以及如何有效地使用JSON进行大规模数据处理。 手册的版权信息指出,除非经过出版商的书面许可,否则不允许复制、存储或传输手册内容。此外,尽管编辑和作者...
本文将深入探讨基于`json-lib.jar`包中的`JSONObject`类的四种常用用法。 1. **创建JSONObject** 创建`JSONObject`最常见的方式是从一个Java对象映射而来。`json-lib.jar`提供了`JsonBeanUtil`工具类,可以将Java...
这种格式在Web服务和客户端之间传输数据时非常常见。 标题“JSON使用实例”暗示我们将探讨如何在实际编程中应用JSON。JSON不仅用于存储数据,还常用于网络请求的响应数据格式,如API调用。以下是一些关于JSON使用的...
在VB(Visual Basic 6)中,处理JSON数据格式文件是一项常见的任务,特别是在与Web服务交互或存储配置信息时。本实例将详细讲解如何利用官方API实现VB对JSON的读写操作,帮助开发者更好地理解这一过程。 首先,JSON...
在Java编程语言中,解析JSON(JavaScript Object Notation)数据是一项常见的任务,因为JSON作为一种轻量级的数据交换格式,广泛用于API交互、存储和传输数据。本篇文章将深入探讨Java中解析JSON的几种主要方法,...
本文主要介绍两种常见的Linux下JSON解析工具:`jsonfilter` 和 `jq`。 #### jsonfilter 工具详解 `jsonfilter` 是一款由OpenWRT自带的工具,其体积小且简单易用,能够满足基本的需求。它基于`json-c`库实现,因此...
在Java开发中,处理JSON数据是一项常见的任务,而Gson和JsonBean是两个常用的库,用于将Java对象转换为JSON格式以及将JSON字符串反序列化为Java对象。本篇文章将详细探讨这两个库的使用方法,并通过一个具体的案例来...
10. 把JSON文本转换为JavaScript对象是JSON数据处理的常见用法。可以使用JavaScript内置的eval()函数进行转换,但需要注意安全性问题,因为eval()会执行字符串中的代码。更安全的替代方法是使用JSON.parse()函数,它...
本篇文章将详细探讨这个过程,以及如何使用常见的Java JSON库,如Gson和Jackson,进行JSON与Java对象的转换。 首先,让我们了解JSON的基本结构。JSON格式通常包含键值对(key-value pairs)和数组。键值对以冒号...
下面我们将深入探讨JSON的基本结构和常见用法。 1. JSON的基本结构: - 对象(Object):以大括号 `{}` 包围,键值对之间用逗号分隔。键(key)必须是字符串,用双引号包围,值(value)可以是各种数据类型,如...
在Java中,处理JSON数据是常见的任务,尤其在开发Web服务、前后端交互等场景中。本篇文章将深入探讨Java中解析和生成JSON的类库,并介绍如何使用它们进行数据转换。 ### JSON的基本结构 JSON基于JavaScript语法,...
标题 "notepad++ json viewer" 描述的是一个用于Notepad++编辑器的插件,它扩展了Notepad++的功能,使用户能够更方便地查看和编辑...对于初次使用者,只需按照README的指示进行操作,就可以轻松掌握这款插件的用法。
1. **获取JSON库**:常见的JSON库有jsoncpp、libjson、nlohmann/json等。例如,nlohmann/json是一个C++11实现的轻量级JSON库,具有良好的API和性能。你可以通过Git或源代码包下载它。 2. **构建和安装**:一旦你有...
5. JSON操作:尝试对JSON对象进行一些常见操作,如获取键值、遍历、修改、删除等,并验证操作结果。 6. 序列化与反序列化:将JSON字符串转换回Java对象,检查数据的完整性和一致性。 7. 性能分析:通过JMH(Java ...
处理复杂的JSON格式并将其转换为Java对象是一项常见的任务,这涉及到JSON库的使用,例如Jackson、Gson或Fastjson等。本资源提供了一个关于如何将复杂JSON转换为Java对象的学习实例,包括源码和可执行的jar包。 一、...
在处理Web应用程序中的数据时,JSON(JavaScript Object Notation)是一种非常常见的数据格式。它轻量级且易于读写,因此广泛应用于前后端的数据交互中。对于Java开发者来说,能够熟练地操作JSON数据是必不可少的...
这些测试用例覆盖了各种边界条件和常见用法,是评估框架质量的重要依据。 综上所述,"LUA的JSON框架"是一个用于在LUA环境中方便地处理JSON数据的工具集,它提供了高效、安全且易用的接口,让开发者可以专注于业务...
在LUA中,常见的JSON库有`json4lua`、`cjson`等。其中,`json4lua`是一个纯LUA编写的库,不需要额外的C扩展,易于安装和使用。在你提供的文件名`json4lua-master`中,我们可以推测这是一个`json4lua`库的版本。要...