private String name;
private int age;
// getter/setter
}
我们来尝试解析一下:
ObjectMapper mapper = new ObjectMapper();
Writer deserializedWriter = mapper.readValue(jsonString, Writer.class);
不出意外,抛出异常了,sex 无法识别。
Exception in thread “main” com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “sex” (class com.itwanger.jackson.Writer), not marked as ignorable (2 known properties: “name”, “age”])
at [Source: (String)"{
“name” : “沉默王二”,
“age” : 18,
“sex” : “男”
}"; line: 4, column: 12] (through reference chain: com.itwanger.jackson.Writer[“sex”])
怎么办呢?可以通过 configure()
方法忽略掉这些“无法识别”的字段。
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
除此之外,还有其他一些有用的配置信息,来了解一下:
// 在序列化时忽略值为 null 的属性
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// 忽略值为默认值的属性
mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
04、处理日期格式
对于日期类型的字段,比如说 java.util.Date,如果不指定格式,序列化后将显示为 long 类型的数据,这种默认格式的可读性很差。
{
“age” : 18,
“birthday” : 1606358621209
}
怎么办呢?
第一种方案,在 getter 上使用 @JsonFormat
注解。
private Date birthday;
// GMT+8 是指格林尼治的标准时间,在加上八个小时表示你现在所在时区的时间
@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm:ss”)
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
再来看一下结果:
{
“age” : 18,
“birthday” : “2020-11-26 03:02:30”
}
具体代码如下所示:
ObjectMapper mapper = new ObjectMapper();
Writer wanger = new Writer(“沉默王二”, 18);
wanger.setBirthday(new Date());
String jsonString = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(wanger);
System.out.println(jsonString);
第二种方案,调用 ObjectMapper 的 setDateFormat()
方法。
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(StdDateFormat.getDateTimeInstance());
Writer wanger = new Writer(“沉默王二”, 18);
wanger.setBirthday(new Date());
String jsonString = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(wanger);
System.out.println(jsonString);
输出结果如下所示:
{
“name” : “沉默王二”,
“age” : 18,
“birthday” : “2020年11月26日 上午11:09:51”
}
05、字段过滤
在将 Java 对象序列化为 JSON 时,可能有些字段需要过滤,不显示在 JSON 中,Jackson 有一种比较简单的实现方式。
@JsonIgnore 用于过滤单个字段。
@JsonIgnore
public String getName() {
return name;
}
@JsonIgnoreProperties 用于过滤多个字段。
@JsonIgnoreProperties(value = { “age”,“birthday” })
class Writer{
private String name;
private int age;
private Date birthday;
}
06、自定义序列化和反序列化
当 Jackson 默认序列化和反序列化不能满足实际的开发需要时,可以自定义新的序列化和反序列化类。
自定义的序列化类需要继承 StdSerializer,同时重写 serialize()
方法,利用 JsonGenerator 生成 JSON,示例如下:
/**
-
微信搜索「沉默王二」,回复 Java
-
@author 沉默王二
-
@date 2020/11/26
*/
public class CustomSerializer extends StdSerializer {
protected CustomSerializer(Class t) {
super(t);
}
public CustomSerializer() {
this(null);
}
@Override
public void serialize(Man value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField(“name”, value.getName());
gen.writeEndObject();
}
}
class Man{
private int age;
private String name;
public Man(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
定义好自定义序列化类后,要想在程序中调用它们,需要将其注册到 ObjectMapper 的 Module 中,示例如下所示:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
new SimpleModule(“CustomSerializer”, new Version(1, 0, 0, null, null, null));
module.addSerializer(Man.class, new CustomSerializer());
mapper.registerModule(module);
Man man = new Man( 18,“沉默王二”);
String json = mapper.writeValueAsString(man);
System.out.println(json);
程序输出结果如下所示:
{“name”:“沉默王二”}
自定义序列化类 CustomSerializer 中没有添加 age 字段,所以只输出了 name 字段。
再来看一下自定义的反序列化类,继承 StdDeserializer,同时重写 deserialize()
方法,利用 JsonGenerator 读取 JSON,示例如下:
public class CustomDeserializer extends StdDeserializer {
protected CustomDeserializer(Class<?> vc) {
super(vc);
}
public CustomDeserializer() {
this(null);
}
@Override
public Woman deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree§;
Woman woman = new Woman();
int age = (Integer) ((IntNode) node.get(“age”)).numberValue();
String name = node.get(“name”).asText();
woman.setAge(age);
woman.setName(name);
return woman;
}
}
class Woman{
private int age;
private String name;
public Woman() {
}
// getter/setter
@Override
public String toString() {
return “Woman{” +
“age=” + age +
“, name='” + name + ‘’’ +
‘}’;
}
}
通过 JsonNode 把 JSON 读取到一个树形结构中,然后通过 JsonNode 的 get 方法将对应字段读取出来,然后生成新的 Java 对象,并返回。
定义好自定义反序列化类后,要想在程序中调用它们,同样需要将其注册到 ObjectMapper 的 Module 中,示例如下所示:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
new SimpleModule(“CustomDeserializer”, new Version(1, 0, 0, null, null, null));
module.addDeserializer(Woman.class, new CustomDeserializer());
mapper.registerModule(module);
String json = “{ “name” : “三妹”, “age” : 18 }”;
Woman woman = mapper.readValue(json, Woman.class);
System.out.println(woman);
程序输出结果如下所示:
Woman{age=18, name=‘三妹’}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip1024b 备注Java获取(资料价值较高,非无偿)
总结
我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。
面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!
GNll26lS-1711551011400)]
[外链图片转存中…(img-eMeTdddg-1711551011401)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
[外链图片转存中…(img-Y4mErOIN-1711551011401)]
[外链图片转存中…(img-UAe9qpJw-1711551011402)]
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V:vip1024b 备注Java获取(资料价值较高,非无偿)
[外链图片转存中…(img-XP5DCoaj-1711551011402)]
总结
我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。
面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!
[外链图片转存中…(img-5q68iogz-1711551011402)]