淘先锋技术网

首页 1 2 3 4 5 6 7



虽然是出问题了,但是序列化并没有转为属性为null的对象,而是直接抛出异常



Exception in thread “main” com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class online.jvm.bean.User and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)

复制代码




通过查询异常资料,解决掉这种异常需要在增加Jackson的序列化配置FAIL\_ON\_EMPTY\_BEANS,FAIL\_ON\_EMPTY\_BEANS这个配置表示如果某个bean序列化为空时不会异常失败



public static void main(String[] args) throws IOException {

ObjectMapper objectMapper = new ObjectMapper();

objectMapper.configure(FAIL_ON_EMPTY_BEANS, false);

String request = objectMapper.writeValueAsString(new User("niu", 18));

System.out.println(request);

}

复制代码




这种就不会报错,而是返回序列化成空串,也就导致接受方为属性都为null



通过看自研RPC框架看到是有该FAIL\_ON\_EMPTY\_BEANS的配置



解决

--



再来分析一下原因,Jackson序列化时需要调用bean的getter方法



### 1、写上getter后再看下结果:



public class User {

private String name;

private Integer age;



public User(String name, Integer age) {

    this.name = name;

    this.age = age;

}



public String getName() {

    return name;

}



public Integer getAge() {

    return age;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    // 输出正常 : {"name":"niu","age":18}

}

}

复制代码




### 2、或者把属性访问权限改为public



public class User {

public String name;

public Integer age;



public User(String name, Integer age) {

    this.name = name;

    this.age = age;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    // 输出正常 : {"name":"niu","age":18}

}

}

复制代码




但是如果要求**不能暴露bean的属性**即使是getter也不行呢?



### 3、注解 `@JsonProperty`



这是就需要使用Jackson提供的注解 `@JsonProperty`



public class User {

@JsonProperty("userName")

private String name;

@JsonProperty

private Integer age;



public User(String name, Integer age) {

    this.name = name;

    this.age = age;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    //   {"userName":"niu","age":18}

}

}

复制代码




来看下注解`@JsonProperty`的源码注释



Marker annotation that can be used to define a non-static method as a “setter” or “getter” for a logical property (depending on its signature), or non-static object field to be used (serialized, deserialized) as a logical property.

复制代码




大体意思是注解如果**用在属性上**相当于为该属性**定义getter和setter**。



那如果既有getter又有`@JsonProperty`注解,以哪个为准呢?



public class User {

@JsonProperty("userName")

private String name;

@JsonProperty

private Integer age;



public User(String name, Integer age) {

    this.name = name;

    this.age = age;

}



public String getName() {

    return name;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    // {"age":18,"userName":"niu"}

}

}

复制代码




如果getter一个没有的属性,效果如何呢?



public class User {

@JsonProperty("userName")

private String name;

@JsonProperty

private Integer age;



public User(String name, Integer age) {

    this.name = name;

    this.age = age;

}



public String getName2() {

    return name;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    // {"age":18,"name2":"niu","userName":"niu"}

}

}

复制代码




**这说明如果有`@JsonProperty`注解,先以注解为准**



然后**利用反射找到对象类的所有get方法**,接下来去get,然后小写化,作为json的每个key值,而get方法的返回值作为value。接下来**再反射field**,添加到json中。



### 4、特殊情况



还有一种比较特殊的情况, getter方法由lombok生成,且属性的次首字母是大写:



@Getter

public class User {

@JsonProperty

private String nAme;

@JsonProperty

private Integer age;



public User(String name, Integer age) {

    this.nAme = name;

    this.age = age;

}



public static void main(String[] args) throws IOException {

    ObjectMapper objectMapper = new ObjectMapper();

    String request = objectMapper.writeValueAsString(new User("niu", 18));

    System.out.println(request);

    // {"nAme":"niu","age":18,"name":"niu"}

}

}

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

如果你需要这份完整版的面试笔记,只需你多多支持我这篇文章。

——对文章进行点赞+评论,关注我,然后再点击这里免费领取

User(“niu”, 18));

    System.out.println(request);

    // {"nAme":"niu","age":18,"name":"niu"}

}

}

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

如果你需要这份完整版的面试笔记,只需你多多支持我这篇文章。

——对文章进行点赞+评论,关注我,然后再点击这里免费领取

[外链图片转存中…(img-4bgv0xJZ-1628129948556)]