Jackson--使用/教程/示例

原文网址:Jackson--使用/教程/示例_IT利刃出鞘的博客-CSDN博客

简介

说明

本文用实例介绍SpringBoot的Jackson的使用。

项目中我们经常会用到JSON,比如:将JSON字符串反序列化为对象、将对象序列华为JSON字符串。

Spring Boot支持与三种JSON mapping库集成:Gson、Jackson和JSON-B。Jackson是默认的。

实际我们常用的是SpringBoot默认的JakckSon与阿里巴巴的FastJson。个人推荐Jackson,因为它基本没有缺陷,而FastJson有很多缺陷。

 Jackson包全路径为:com.fasterxml.jackson.annotation.*

官网

https://github.com/FasterXML/jackson

依赖 

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Jackson是spring-boot-starter-json的一个依赖(spring-boot-starter-web中包含spring-boot-starter-json)。也就是说,当项目中引入spring-boot-starter-web后会自动引入spring-boot-starter-json。 

ObjectMapper如何匹配JSON对象的字段和Java对象的属性

默认情况下,Jackson通过将JSON字段的名称与Java对象中的getter和setter方法进行匹配,将JSON对象的字段映射到Java对象中的属性。 Jackson删除了getter和setter方法名称的“ get”和“ set”部分,并将其余名称的第一个字符转换为小写。

例如,名为brand的JSON字段与名为getBrand()和setBrand()的Java getter和setter方法匹配。 名为engineNumber的JSON字段将与名为getEngineNumber()和setEngineNumber()的getter和setter匹配。

如果需要以其他方式将JSON对象字段与Java对象字段匹配,则需要使用自定义序列化器和反序列化器,或者使用一些Jackson注解。 

创建ObjectMapper

法1:注入ObjectMapper

@Autowired
private ObjectMapper objectMapper;

这样可以使用SpringBoot已经配置好的ObjectMapper,它比较好用。

例如:LocaltDateTime加了@JsonFormat注解后可以指定序列化格式:

{"createTime":"2022-03-17 10:07:55"}

如果用private ObjectMapper objectMapper = new ObjectMapper();,则序列化后的结果为:

{"createTime":{"month":"MARCH","year":2022,"dayOfMonth":17,"hour":10,"minute":5,"monthValue":3,"nano":395000000,"second":41,"dayOfWeek":"THURSDAY","dayOfYear":76,"chronology":{"id":"ISO","calendarType":"iso8601"}}}

法2:新建ObjectMapper

private ObjectMapper objectMapper = new ObjectMapper();

注解

官网

https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations

通用注解(序列化/反序列化都有效)

注解

使用位置

含义

@JsonIgnore

field、getter、

setter、构造方法

不进行序列化/反序列化。放任意位置,都意味着忽略所有(即序列化和反序列化都被忽略)。

若setter上注解@JsonIgnore而getter上注解@JsonProperty,就会出现“只读”情况(read from input, but is not written output)。

@JsonProperty

字段

指定外部属性名字。即:使用别名序列化,而不是对象的名字。

例:

@JsonProperty("username")
private String userName;

@JsonIgnoreProperties

忽略属性,多个时用“,”隔开。与@JsonIgnore作用一致。

@JsonIgnoreProperties(ignoreUnknown = true):会忽略类中不存在的字段。

@JsonIgnoreType

当其他类有该类作为属性时,该属性将被忽略。

序列化注解(只在序列化时有效)

注解

使用位置

含义

@JsonPropertyOrder

指定属性在 json 字符串中的顺序。

示例:@JsonPropertyOrder(value={"id","name"})

@JsonFormat

字段

序列化为json后的格式。

示例:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private LocalDateTime localDateTime;

@JsonInclude

属性、类

排除属性。用于类:排除所有。

示例:@JsonInclude(JsonInclude.Include.NON_NULL)

只有属性不为 null 时才序列化

成员

含义

ALWAYS

无论对象属性是不是空,都输出到json字符串中(默认值)

NON_NULL

序列化生成的json字符串仅包括非null的字段属性

NON_ABSENT

NON_NULL的增强版,比如jdk和谷歌Guava的Optional类型对象,不是null,但它的isPresent方法返回false

NON_EMPTY

非空:指非null,非""。集合isEmpty()==true的将被忽略

NON_DEFAULT

属性值为缺省值时不序列化,如int类型属性==0,String类型属性==null等

CUSTOM

结合注解JsonInclude.valueFilter和JsonInclude.contentFilter使用,这两个注解会指定一个Class,然后默认调用这个Class的空参构造方法,返回的对象eques属性值的话,序列化时就忽略。如使用注解:@JsonInclude(valueFilter=String.class),然后javabean中String name="";则这个name在序列化为json时将被忽略,因为"".equals(new String())

@JsonAnyGetter

getter方法

像普通属性一样序列化Map

@JsonGetter

getter方法

跟@JsonProperty等效

@JsonPropertyOrder

在序列化的时候自定义属性输出顺序

@JsonRawValue

字段

按照原样序列化属性的值。

@JsonValue

方法、字段

定义整个实体的序列化方法,Jackson将会使用该方法的输出作为序列化输出。

类似于toString方法

@JsonRootName

如果需要将实体包装一层,可以使用@JsonRootName来指定根包装器的名称

@JsonSerialize

字段、getter方法

指定自定义序列化器来序列化实体

反序列化注解(只在反序列化时有效)

注解

使用位置

含义

@JsonCreator

方法、构造器

指定反序列化使用的构造函数或方法

实例:

@JsonCreator
public BeanWithCreator(@JsonProperty("id") int id, @JsonProperty("theName") String name) {

    this.id = id;

    this.name = name;
}

@JacksonInject

方法、字段、参数

指定某个字段从注入赋值,而不是从Json

@JsonAnySetter

方法、字段

在反序列化时,将Map当成普通属性

@JsonAnySetter

setter方法

指定反序列化时的名称

@JsonDeserialize

字段、setter方法

指定自定义反序列化器来反序列化实体

JSON转对象

作用

方法

JSON字符串--> Java对象

Car car = new ObjectMapper().readValue(jsonString, Car.class);

JSON 字符输入流--> Java对象

ObjectMapper objectMapper = new ObjectMapper();

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 4 }";
Reader reader = new StringReader(carJson);

Car car = objectMapper.readValue(reader, Car.class);

JSON文件--> Java对象

ObjectMapper objectMapper = new ObjectMapper();

File file = new File("data/car.json");

Car car = objectMapper.readValue(file, Car.class);

JSON via URL--> Java对象

ObjectMapper objectMapper = new ObjectMapper();

URL url = new URL("file:data/car.json");

Car car = objectMapper.readValue(url, Car.class);

示例使用文件URL,也可用HTTP URL(例:http://jenkov.com/some-data.json)。

JSON字节输入流--> Java对象

ObjectMapper objectMapper = new ObjectMapper();

InputStream input = new FileInputStream("data/car.json");

Car car = objectMapper.readValue(input, Car.class);

JSON二进制数组--> Java对象

ObjectMapper objectMapper = new ObjectMapper();

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";

byte[] bytes = carJson.getBytes("UTF-8");

Car car = objectMapper.readValue(bytes, Car.class);

JSON数组字符串--> Java对象数组

String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";

ObjectMapper objectMapper = new ObjectMapper();

Car[] cars2 = objectMapper.readValue(jsonArray, Car[].class);

JSON数组字符串--> List

 String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";

 ObjectMapper objectMapper = new ObjectMapper();

 List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});

JSON字符串--> Map

(通用类型的Map)

String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";

ObjectMapper objectMapper = new ObjectMapper();
Map jsonMap = objectMapper.readValue(jsonObject, Map.class);

JSON字符串--> Map

(指定类型的Map)

String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";

ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> jsonMap = objectMapper.readValue(jsonObject,
    new TypeReference<Map<String, String>>(){});

泛型

实例

Entity

package com.example.entity;

import lombok.Data;

@Data
public class User {
    private String userName;
    private Integer age;
}

Controller

package com.example.controller;

import com.example.entity.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Type;
import java.util.List;

@RestController
public class HelloController {

    @GetMapping("/test")
    public String test() throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();

        // 转为泛型Type指定的类型
        //{"userName":"Tony", "age":22}
        String json1 = "{\"userName\":\"Tony\", \"age\":22}";
        Type type1 = User.class;
        JavaType javaType1 = objectMapper.getTypeFactory().constructType(type1);
        User user = objectMapper.readValue(json1, javaType1);
        System.out.println("json1: " + user);

        // 转为泛型Type指定的类型
        //{"success": true, "data": [{"userName":"Tony", "age":22}, {"userName":"Pepper", "age":21}]}
        String json2 = "{\"success\": true, \"data\": [{\"userName\":\"Tony\", \"age\":22}," +
                " {\"userName\":\"Pepper\", \"age\":21}]}";
        Type type2 = Object.class;
        JavaType javaType2 = objectMapper.getTypeFactory().constructType(type2);
        Object object = objectMapper.readValue(json2, javaType2);
        System.out.println("json2: " + object);

        // 转为泛型TypeReference里的类型
        //{"userName":"Tony", "age":22}
        String json3 = "{\"userName\":\"Tony\", \"age\":22}";
        User user1 = objectMapper.readValue(json3, new TypeReference<User>() {});
        System.out.println("json3: " + user1);

        // 将JSON数组转为List
        //[{"userName":"Tony", "age":22}, {"userName":"Pepper", "age":21}]
        String json4 = "[{\"userName\":\"Tony\", \"age\":22}, {\"userName\":\"Pepper\", \"age\":21}]";
        JavaType javaType4 = objectMapper.getTypeFactory().constructCollectionType(List.class, User.class);
        List<User> userList4 = objectMapper.readValue(json4, javaType4);
        System.out.println("json4: " + userList4);

        // 将JSON数组转为List
        //[{"userName":"Tony", "age":22}, {"userName":"Pepper", "age":21}]
        String json5 = "[{\"userName\":\"Tony\", \"age\":22}, {\"userName\":\"Pepper\", \"age\":21}]";
        JavaType javaType5 = objectMapper.getTypeFactory().constructCollectionType(List.class, User.class);
        List<User> userList5 = objectMapper.readValue(json5, javaType5);
        System.out.println("json5: " + userList5);

        return "test success";
    }
}

测试

访问:http://localhost:8080/test

后端结果:

对象转JSON

方法作用
String str = new ObjectMapper().writeValueAsString(obj)Object转JSON字符串
byte[] bytes = new ObjectMapper().writeValueAsBytes(obj)Object转JSON字节数组

日期转化

        默认情况下,Jackson会将java.util.Date对象序列化为其long型的值,该值是自1970年1月1日以来的毫秒数。但是,Jackson还支持将日期格式化为字符串。

Date-->long(默认)

该格式将Date序列化为自1970年1月1日以来的毫秒数(long类型)。

@Data
public class Transaction{}
    private String type = null;
    private Date date = null;

    public Transaction() {
    }

    public Transaction(String type, Date date) {
        this.type = type;
        this.date = date;
    }
}
  Transaction transaction = new Transaction("transfer", new Date());

  ObjectMapper objectMapper = new ObjectMapper();
  String output = objectMapper.writeValueAsString(transaction);

  System.out.println(output);

 运行结果

Date-->String(自定义)

        Jackson也支持文本日期格式。 可在ObjectMapper上设置SimpleDateFormat来指定要使用的Jackson日期格式。

  Transaction transaction = new Transaction("transfer", new Date());

  ObjectMapper objectMapper = new ObjectMapper();
  SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  objectMapper.setDateFormat(dateFormat);

  String output2 = objectMapper.writeValueAsString(transaction);
  System.out.println(output2);

运行结果

树模型

简介

         Jackson具有内置的树模型,可用于表示JSON对象。 如果不知道接收到的JSON的格式,或者由于某种原因而不能(或者只是不想)创建一个类来表示它,那么就要用到Jackson的树模型。 如果需要在使用或转化JSON之前对其进行操作,也需要被用到Jackson树模型。 所有这些情况在数据流场景中都很常见。

        Jackson树模型由JsonNode类表示。 您可以使用Jackson ObjectMapper将JSON解析为JsonNode树模型,就像使用您自己的类一样。

JsonNode vs ObjectNode

Jackson JsonNode类是不可变的。 这意味着,实际上不能直接构建JsonNode实例的对象图。 而是创建JsonNode子类ObjectNode的对象图。 作为JsonNode的子类,可以在可以使用JsonNode的任何地方使用ObjectNode。

 Jackson Tree Model简单例子

// {
//     "brand": "Mercedes",
//     "doors": 5
// }

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";

ObjectMapper objectMapper = new ObjectMapper();

try {

  JsonNode jsonNode = objectMapper.readTree(carJson);
  // 或者JsonNode jsonNode = objectMapper.readValue(carJson, JsonNode.class);

} catch (IOException e) {
  e.printStackTrace();
}

访问JSON字段,数组和嵌套对象

// {
//     "brand": "Mercedes",
//     "doors": 5,
//     "owners": ["John", "Jack", "Jill"],
//     "nestedObject": {
//         "field": "value"
//     }
// }

String carJson =
        "{ \"brand\" : \"Mercedes\", \"doors\" : 5," +
        "  \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +
        "  \"nestedObject\" : { \"field\" : \"value\" } }";

ObjectMapper objectMapper = new ObjectMapper();

try {
    JsonNode jsonNode = objectMapper.readTree(carJson);

    JsonNode brandNode = jsonNode.get("brand");
    String brand = brandNode.asText();
    System.out.println("brand = " + brand);

    JsonNode doorsNode = jsonNode.get("doors");
    int doors = doorsNode.asInt();
    System.out.println("doors = " + doors);

    JsonNode array = jsonNode.get("owners");
    JsonNode jsonNode = array.get(0);
    String john = jsonNode.asText();
    System.out.println("john  = " + john);

    JsonNode child = jsonNode.get("nestedObject");
    JsonNode childField = child.get("field");
    String field = childField.asText();
    System.out.println("field = " + field);

} catch (IOException e) {
    e.printStackTrace();
}

        将JSON解析为JsonNode(或JsonNode实例树)后,就可以浏览JsonNode树模型。 

        请注意,JSON字符串现在包含一个称为owners的数组字段和一个称为nestedObject的嵌套对象字段。

        无论访问的是字段,数组还是嵌套对象,都可以使用JsonNode类的get()方法。 通过将字符串作为参数提供给get()方法,可以访问JsonNode的字段。 如果JsonNode表示数组,则需要将索引传递给get()方法。 索引指定要获取的数组元素。

示例(很全)

作用

方法

说明

Java对象-->JsonNode

ObjectMapper objectMapper = new ObjectMapper();

Car car = new Car();
car.brand = "Cadillac";
car.doors = 4;

JsonNode carJsonNode = objectMapper.valueToTree(car);

JsonNode是转换后的Java对象的JSON表示形式。 可以通过Jackson ObjectMapper valueToTree()方法将Java对象转换为JsonNode。

JsonNode-->Java对象

ObjectMapper objectMapper = new ObjectMapper();

String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";

JsonNode carJsonNode = objectMapper.readTree(carJson);

Car car = objectMapper.treeToValue(carJsonNode);

示例有点“人为”,因为我们首先将JSON字符串转换为JsonNode,然后将JsonNode转换为Car对象。 显然,如果我们有对原始JSON字符串的引用,则最好将其直接转换为Car对象,而无需先将其转换为JsonNode。

JSON-->JsonNode

String json = "{ \"f1\" : \"v1\" } ";

ObjectMapper objectMapper = new ObjectMapper();

JsonNode jsonNode = objectMapper.readTree(json);

System.out.println(jsonNode.get("f1").asText());

要使用Jackson将JSON读取到JsonNode中,首先需要创建一个Jackson ObjectMapper实例。 在ObjectMapper实例上,调用readTree()并将JSON源作为参数传递。

JsonNode-->JSON

ObjectMapper objectMapper = new ObjectMapper();

JsonNode jsonNode = readJsonIntoJsonNode();

String json = objectMapper.writeValueAsString(jsonNode);

要将Jackson的JsonNode写入JSON,还需要一个Jackson ObjectMapper实例。 在ObjectMapper上,调用writeValueAsString()方法或任何适合需要的写入方法

获取JsonNode字段

假设已将以下JSON解析为JsonNode

{
    "field1" : "value1",
    "field2" : 999
}

此JSON对象具有两个名为field1和field2的字段。 如果有一个表示上述JSON对象的Jackson JsonNode,则可以这样获得两个字段:

JsonNode jsonNode = ... //parse above JSON into a JsonNode

JsonNode field1 = jsonNode.get("field1");
JsonNode field2 = jsonNode.get("field2");

JsonNode可以像JSON对象一样具有字段。

即使两个字段都是String字段,get()方法也始终返回JsonNode来表示该字段。

路径中获取JsonNode字段

假设JSON结构如下所示:

{
  "identification" :  {
        "name" : "James",
        "ssn: "ABC123552"
    }
}
将此JSON解析为JsonNode,可用at()方法访问名称字段

JsonNode nameNode = jsonNode.at("/identification/name");

        Jackson JsonNode有一个称为at()的特殊方法。 at()方法可以从JSON图中以给定JsonNode为根的任何位置访问JSON字段。

        注意传递给at()方法的参数:字符串/ identification / name。 这是一个JSON路径表达式。 此路径表达式指定从根JsonNode到您要访问其值的字段的完整路径。 这类似于从文件系统根目录到Unix文件系统中文件的路径。

请注意,JSON路径表达式必须以斜杠字符(/字符)开头。

        at()方法返回一个JsonNode,它表示请求的JSON字段。 要获取该字段的实际值,需要调用下一部分介绍的方法之一。 如果没有节点与给定的路径表达式匹配,则将返回null。

转换JsonNode字段

String f2Str = jsonNode.get("f2").asText();
double f2Dbl = jsonNode.get("f2").asDouble();
int    f2Int = jsonNode.get("f2").asInt();
long   f2Lng = jsonNode.get("f2").asLong();

//使用默认值转换

ObjectMapper objectMapper = new ObjectMapper();

String json = "{ \"f1\":\"Hello\", \"f2\":null }";

JsonNode jsonNode = objectMapper.readTree(json);

String f2Value = jsonNode.get("f2").asText("Default");

//错误示例

 ObjectMapper objectMapper = new ObjectMapper();

String json = "{ \"f1\":\"Hello\" }";

JsonNode jsonNode = objectMapper.readTree(json);

JsonNode f2FieldNode = jsonNode.get("f2");

        Jackson JsonNode类包含一组可以将字段值转换为另一种数据类型的方法。 例如,将String字段值转换为long或相反。

        使用默认值转换: 如果JsonNode中的字段可以为null,则在尝试转换它时可以提供默认值。 

        在示例的JSON字符串中可以看到,声明了f2字段,但将其设置为null。 在这种情况下,调用jsonNode.get(“ f2”)。asText(“ Default”)将返回默认值,在此示例中为字符串Default。

asDouble(),asInt()和asLong()方法还可以采用默认参数值,如果尝试从中获取值的字段为null,则将返回默认参数值。

        请注意,如果该字段在JSON中未显式设置为null,但在JSON中丢失,则调用jsonNode.get(“ fieldName”)将返回Java null值,您无法在该Java值上调用asInt() ,asDouble(),asLong()或asText()。 如果尝试这样做,将会导致NullPointerException。

创建一个ObjectNode

ObjectMapper objectMapper = new ObjectMapper();

ObjectNode objectNode = objectMapper.createObjectNode();

        如前所述,JsonNode类是不可变的。 要创建JsonNode对象图,必须能够更改图中的JsonNode实例,例如 设置属性值和子JsonNode实例等。由于是不可变的,因此无法直接使用JsonNode来实现。而是创建一个ObjectNode实例,该实例是JsonNode的子类。

Set ObjectNode字段

ObjectMapper objectMapper = new ObjectMapper();
ObjectNode parentNode = objectMapper.createObjectNode();

JsonNode childNode = readJsonIntoJsonNode();

parentNode.set("child1", childNode);

要在Jackson ObjectNode上设置字段,可以调用其set()方法,并将字段名称String和JsonNode作为参数传递。

Put ObjectNode字段

objectNode.put("field1", "value1");
objectNode.put("field2", 123);
objectNode.put("field3", 999.999);

ObjectNode类还具有一组方法,可以直接为字段put(设置)值。 这比尝试将原始值转换为JsonNode并使用set()进行设置要容易得多。 

删除字段

objectNode.remove("fieldName");

ObjectNode类具有一个称为remove()的方法,该方法可用于从ObjectNode中删除字段。 

循环JsonNode字段

Iterator<String> fieldNames = jsonNode.fieldNames();

while(fieldNames.hasNext()) {
    String fieldName = fieldNames.next();

    JsonNode field = jsonNode.get(fieldName);
}

JsonNode类具有一个名为fieldNames()的方法,该方法返回一个Iterator,可以迭代JsonNode的所有字段名称。 我们可以使用字段名称来获取字段值。

问题解决

无序列化器

场景

package com.example.config;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.Map;

@Component
public class ApplicationContextTest implements ApplicationContextAware, ApplicationRunner {
    private ApplicationContext applicationContext;

    RequestMappingHandlerMapping handlerMapping;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        handlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
    }

    public RequestMappingHandlerMapping getHandlerMapping() {
        return handlerMapping;
    }
}
package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.example.config.ApplicationContextTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @Autowired
    ApplicationContextTest applicationContextTest;

    @GetMapping("/test1")
    public String test1() {
        return "hello";
    }

    @GetMapping("/test2")
    public String test2() throws JsonProcessingException {
        System.out.println(new ObjectMapper().writeValueAsString(applicationContextTest.getHandlerMapping()));
        return "hehe";
    }
}

错误日志:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.springframework.boot.context.properties.source.SoftReferenceConfigurationPropertyCache and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping["applicationContext"]->org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext["environment"]->org.springframework.web.context.support.StandardServletEnvironment["propertySources"]->org.springframework.boot.context.properties.source.ConfigurationPropertySourcesPropertySource["source"]->org.springframework.boot.context.properties.source.SpringIterableConfigurationPropertySource["caching"])

解决方法:配置ObjectMapper这个bean,关闭空bean的报错,使用ObjectMapper时直接注入

package com.example.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class ObjectMapperConfiguration {
    @Bean
    public ObjectMapper objectMapper() {
        return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    }
}

package com.example.controller;

import com.alibaba.fastjson.JSON;
import com.example.config.ApplicationContextTest;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {
    @Autowired
    ApplicationContextTest applicationContextTest;

    @Autowired
    ObjectMapper objectMapper;

    @GetMapping("/test1")
    public String test1() {
        return "hello";
    }

    @GetMapping("/test2")
    public String test2() throws JsonProcessingException {
        System.out.println(objectMapper.writeValueAsString(applicationContextTest.getHandlerMapping()));
        return "hehe";
    }
}

但是,又报其他错误(死循环了):

Caused by: java.lang.StackOverflowError: null

其他网址

Jackson使用详解 - 掘金

Jackson使用指南 - 掘金 (实例很全)

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT利刃出鞘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值