当前位置: 首页 > news >正文

轻松上手Jackjson(珍藏版)

写在前面

虽然现在市面上有很多优秀的json解析库,但 Spring默认采用Jackson解析Json。

本文将通过一系列通俗易懂的代码示例,带你逐步掌握 Jackson 的基础用法、进阶技巧以及在实际项目中的应用场景。

一、Jackjson简介

Jackson 是当前用的比较广泛的,用来序列化和反序列化 json 的 Java 的开源框架。

什么是序列化和反序列化呢?

  • 序列化:将 Java Bean 转换为JSON 字符串

  • 反序列化:将JSON字符串转换为JavaBeen对象

GitHub地址:GitHub - FasterXML/jackson: Main Portal page for the Jackson project

从GitHub 看到,目前有8.8k stars,最近更新时间是2个月前。可见其更新速度还是比较活跃的

也是json最流行的解析器之一

二、Jackjson优点

  • Jackson 所依赖的 jar 包较少,简单易用

  • 其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快

  • Jackson 运行时占用内存比较低,性能比较好

  • Jackson 有灵活的 API,可以很容易进行扩展和定制

三、Jackjson模块及依赖

① Jackson库包括三个主要的模块

  • jackson-databind用于数据绑定

  • jackson-core用于JSON解析和生成

  • jackson-annotations用于注解支持

② 所需依赖

jackson-databind 依赖 jackson-core 和 jackson-annotations,所以可以只显示地添加jackson-databind依赖,jackson-core 和 jackson-annotations 也随之添加到 Java 项目工程中

maven

<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.15.3</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.15.2</version>
</dependency>
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.2</version>
</dependency>

Gradle

dependencies {implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.4'
}

四、快速上手

假设我们有一个简单的 User 类:

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class User {private String name;private int age;
}

4.1 Java对象转JSON字符串
@Test
public void testSerializationExample() throws JsonProcessingException {User user = new User("小凡", 18);ObjectMapper objectMapper = new ObjectMapper();String userstr = objectMapper.writeValueAsString(user);System.out.println(userstr);
}
//输出
{"name":"小凡","age":18}

4.2 JSON字符串转Java对象
@Test
public void testDeserializationExample() throws JsonProcessingException {String json ="{\"name\":\"小凡\",\"age\":18}";ObjectMapper objectMapper = new ObjectMapper();User user = objectMapper.readValue(json, User.class);System.out.println(user);}
//输出
User(name=小凡, age=18)

上面例子中我们我们使用了ObjectMapper 它是 Jackson 库的核心类,负责实现 Java 对象与 JSON 文本之间的相互转换

五、Jackjson序列化API

5.1 普通Java对象序列化
@Test
public void testObjectToJson() throws JsonProcessingException {User user = new User();user.setName("小凡");user.setAge(18);ObjectMapper mapper = new ObjectMapper();String userstr = mapper.writeValueAsString(user);System.out.println(userstr);
}
//输出
{"name":"小凡","age":18}

5.2 复杂对象序列化

① 构造作者出版信息对象

//书籍对象
@Data
public class Book {private String bookName;private String publishDate;private String publishHouse;private Double price;}
//地址对象
@Data
public class Address {private String city;private String street;
}
//作者出版信息对象
@Data
public class PublishInfo {private String name;private String sex;private Integer age;private Address addr;private List<Book> books;
}

② 复杂对象转JSON字符串

@Test
public void testComplexObjectToJson() throws JsonProcessingException {//构造所有出版的书籍listArrayList<Book> books = new ArrayList<Book>();Book book1 = new Book();book1.setBookName("Java从入门到放弃");book1.setPublishDate("2004-01-01");book1.setPublishHouse("小凡出版社");book1.setPrice(66.66);Book book2 = new Book();book2.setBookName("Spring从入门到入土");book2.setPublishDate("2024-01-01");book2.setPublishHouse("小凡出版社");book2.setPrice(88.88);books.add(book1);books.add(book2);//构造作者地址信息Address addr = new Address();addr.setCity("昆明");addr.setStreet("xxx区xxx路xxx号");//构造作者出版的所有书籍信息PublishInfo publishInfo = new PublishInfo();publishInfo.setName("小凡");publishInfo.setSex("男");publishInfo.setAge(18);publishInfo.setAddr(addr);publishInfo.setBooks(books);ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(publishInfo);System.out.println(json);
}
//返回
{"name":"小凡","sex":"男","age":18,"addr":{"city":"昆明","street":"xxx区xxx路xxx号"},"books":[{"bookName":"Java从入门到放弃","publishDate":"2004-01-01","publishHouse":"小凡出版社","price":66.66},{"bookName":"Spring从入门到入土","publishDate":"2024-01-01","publishHouse":"小凡出版社","price":88.88}]}

5.3 List集合序列化
 @Test
public void testListToJson() throws JsonProcessingException {User user1 = new User();user1.setName("小凡001");user1.setAge(18);User user2 = new User();user2.setName("小凡002");user2.setAge(30);ArrayList<User> users = new ArrayList<>();users.add(user1);users.add(user2);ObjectMapper mapper = new ObjectMapper();String userstr = mapper.writeValueAsString(users);System.out.println(userstr);}
//输出
[{"name":"小凡001","age":18},{"name":"小凡002","age":30}]

5.4 Map集合序列化

@Test
public void testMapToJson() throws JsonProcessingException {User user = new User();user.setName("小凡");user.setAge(18);List<String> asList = Arrays.asList("抽烟", "喝酒", "烫头发");HashMap<String, Object> map = new HashMap<>();map.put("user", user);map.put("hobby",asList);ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(map);System.out.println(json);
}
//输出
{"user":{"name":"小凡","age":18},"hobby":["抽烟","喝酒","烫头发"]}

@Test
public void testMapToJsonSup() throws JsonProcessingException {User user1 = new User();user1.setName("小凡001");user1.setAge(18);User user2 = new User();user2.setName("小凡002");user2.setAge(30);ArrayList<User> users = new ArrayList<>();users.add(user1);users.add(user2);List<String> asList = Arrays.asList("抽烟", "喝酒", "烫头发");HashMap<String, Object> map = new HashMap<>();map.put("users", users);map.put("hobby",asList);map.put("name","张三");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(map);System.out.println(json);
}
//输出
{"name":"张三","users":[{"name":"小凡001","age":18},{"name":"小凡002","age":30}],"hobby":["抽烟","喝酒","烫头发"]}

5.5 日期处理

默认情况下,jackjson会将日期类型属性序列化成long型值(自1970年1月1日以来的毫秒数)。显然这样格式的数据不符合人类直观查看

假设我们有个Person对象

@Data
public class Person {private String name;private Date birthday;
}

① 我们先来看看默认转换的结果

@Test
public void testDateToJsonDefault() throws JsonProcessingException {Person person = new Person();person.setName("小凡");person.setBirthday(new Date());ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(person);System.out.println(json);}
//输出
{"name":"小凡","birthday":1712220896407}

② 通过SimpleDateFormat 将日期格式化成人类可看格式显示

@Test
public void testDateToJson() throws JsonProcessingException {Person person = new Person();person.setName("小凡");person.setBirthday(new Date());ObjectMapper mapper = new ObjectMapper();//进行一下日期转换SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");mapper.setDateFormat(dateFormat);String json = mapper.writeValueAsString(person);System.out.println(json);}
//输出  这个格式就人性化多了
{"name":"小凡","birthday":"2024-04-04"}

六、Jackjson反序列化API

Jackson通过将JSON字段的名称与Java对象中的getter和setter方法进行匹配,将JSON对象的字段映射到Java对象中的属性。

Jackson删除了getter和setter方法名称的“ get”和“ set”部分,并将其余名称的第一个字符转换为小写。

6.1 普通JSON字符串反序列化

6.1.1 JSON字符串->Java对象

注: 这里我们还是使用前面小节中创建的User 实体类

@Test
public void testStrToObject() throws JsonProcessingException {String json ="{\"name\":\"小凡\",\"age\":18}";ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(json, User.class);System.out.println(user);
}
//输出
User(name=小凡, age=18)

6.1.2 字符输入流-->Java对象
@Test
public void testReaderToObject() throws JsonProcessingException {String json ="{\"name\":\"小医仙\",\"age\":18}";Reader reader = new StringReader(json);ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(json, User.class);System.out.println(user);
}
//输出
User(name=小医仙, age=18)

6.1.3 字节输入流->Java对象

① 创建user001.json文件,文件内容如下

image-20240404204833787

②将字节输入流转换为User对象

@Test
public void testInputStreamToObject() throws IOException {FileInputStream inputStream = new FileInputStream("F:\\vueworkspace\\jackjson-demo\\jackjson-demo\\src\\json\\user001.json");ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(inputStream, User.class);System.out.println(user);}
}
//输出
User(name=萧炎, age=18)

6.1.4 JSON 文件反->Java对象

①我们准备一个user.json文件,内容如下

image-20240404173608592

② 读取user.json文件中内容,并转换成User 对象

@Test
public void testJsonfileToObject() throws IOException {File file = new File("F:\\vueworkspace\\jackjson-demo\\jackjson-demo\\src\\json\\user.json");ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(file, User.class);System.out.println(user);}
//输出
User(name=萧炎, age=18)

6.1.5 URL文件->Java对象

① 我们在网络上放一个user.json资源文件,内容如下

{"name":"紫妍","age":18}

② 通过URL(java.net.URL) 将JSON转换成User对象

@Test
public void testUrlToObject() throws IOException {String url ="https://files.cnblogs.com/files/blogs/685650/user.json";URL url1 = new URL(url);ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(url1, User.class);System.out.println(user);
}
//输出
User(name=紫妍, age=18)

6.1.6 字节数组-> java对象
@Test
public void testByteToObject() throws IOException {String json ="{\"name\":\"韩雪\",\"age\":18}";byte[] bytes = json.getBytes();ObjectMapper mapper = new ObjectMapper();User user = mapper.readValue(bytes, User.class);System.out.println(user);}
//输出
User(name=韩雪, age=18)

6.2 JSON数组字符串 反序列化
6.2.1 JSON字符串->Map集合
@Test
public void testJsonStrToMap() throws JsonProcessingException {//{"name":"小凡","sex":"男","age":18}String json ="{\"name\":\"小凡\",\"sex\":\"男\",\"age\":18}";ObjectMapper mapper = new ObjectMapper();Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});System.out.println(map);
}
//输出
{name=小凡, sex=男, age=18}

6.2.2 JSON数组字符串->List集合
@Test
public void testJsonArrToList() throws JsonProcessingException {//[{"name":"小凡001","age":18},{"name":"小凡002","age":30}]String json ="[{\"name\":\"小凡001\",\"age\":18},{\"name\":\"小凡002\",\"age\":30}]";ObjectMapper mapper = new ObjectMapper();List<User> users = mapper.readValue(json, new TypeReference<List<User>>() {});System.out.println(users);
}
//输出
[User(name=小凡001, age=18), User(name=小凡002, age=30)]

6.2.3 JSON数组字符串->Java对象数据
@Test
public void testJsonArrToObjArr() throws JsonProcessingException {//[{"name":"小凡001","age":18},{"name":"小凡002","age":30}]String json ="[{\"name\":\"小凡001\",\"age\":18},{\"name\":\"小凡002\",\"age\":30}]";ObjectMapper mapper = new ObjectMapper();User[] users = mapper.readValue(json, User[].class);for (User user : users) {System.out.println(user);}
}
//输出
User(name=小凡001, age=18)
User(name=小凡002, age=30)

七、自定义序列化反序列化

通过自定义序列化和反序列化可以使其更加灵活多变

7.1 自定义序列化

有时候,我们不需要jackjson默认的序列化方式。例如,JSON中使用与Java对象中不同的属性名称,

或者不需要Java对象中的某个字段,这时我们就需要自定义序列化器

我们先来看看User实体对象的定义如下

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

按照下面默认序列化代码,我们最后得到的JSON字符串如下

@Test
public void testSerializationExample() throws JsonProcessingException {User user = new User("小凡", 18);ObjectMapper objectMapper = new ObjectMapper();String userstr = objectMapper.writeValueAsString(user);System.out.println(userstr);
}
//输出
{"name":"小凡","age":18}

而现在的需求升级了,再不创建或修改Users实体对象的情况下,我们想要得到{"username":"小凡","userage":18} 这样的字符串,

应该怎么办呢?

这时,我们就需要自定义序列化器,就可以轻松实现,具体代码如下

 @Test
public void testDefineSerialize() throws JsonProcessingException {SimpleModule version1Module = new SimpleModule();version1Module.addSerializer(User.class, new JsonSerializer<User>() {@Overridepublic void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeStartObject();jsonGenerator.writeStringField("username", user.getName());jsonGenerator.writeNumberField("userage", user.getAge());jsonGenerator.writeEndObject();}});ObjectMapper objectMapper = new ObjectMapper();objectMapper.registerModule(version1Module);User user = new User("小凡", 18);String json = objectMapper.writeValueAsString(user); // 使用版本1的序列化器System.out.println( json);}
//输出
{"username":"小凡","userage":18}

7.2 自定义反序列化器

同理,反序列化也可以自定义,具体代码如下

① 自定义一个反序列化器

public class UserDeserializer extends StdDeserializer<User> {public UserDeserializer() {this(null);}public UserDeserializer(Class<?> vc) {super(vc);}@Overridepublic User deserialize(JsonParser jp, DeserializationContext ctxt)throws IOException {JsonNode node = jp.getCodec().readTree(jp);String name = node.get("name").asText();int age = (Integer) ((IntNode) node.get("age")).numberValue();return new User(name, age);}
}

②将JSON字符串反序列化为 User 对象

@Test
public void testUserDeserializer() throws JsonProcessingException {ObjectMapper objectMapper = new ObjectMapper();SimpleModule module = new SimpleModule();module.addDeserializer(User.class, new UserDeserializer());objectMapper.registerModule(module);String json = "{\"name\":\"小凡\",\"age\":30}";User user = objectMapper.readValue(json, User.class);System.out.println(user);}
//输出
User(name=小凡, age=30)

八、树模型

Jackson具有内置的树模型,可用于表示JSON对象。Jackson树模型由JsonNode类表示。

在处理JSON时,我们有时并不直接关心或无法直接映射到特定的Java对象,而是需要对JSON内容进行动态、灵活的操作。

这时,树模型就派上了用场。我们可以遍历、查询、更新或合并JSON数据,而无需预先定义对应的Java类

8.1 JsonNode类型概览

JsonNode家族包括以下主要子类型:

  • ObjectNode:对应JSON对象,包含一组键值对,可以通过.put(key, value)添加或更新属性。

  • ArrayNode:对应JSON数组,包含一系列元素,可通过.add(value)插入新元素。

  • TextNodeIntNodeLongNodeDoubleNode等:分别对应JSON中的字符串、整数、长整数、浮点数等基本类型值。

  • BooleanNodeNullNode:分别对应JSON中的布尔值和null值。

8.2 创建与操作JsonNode实例

下面通过一些具体的代码示例,展示如何使用JackJson的树模型API来创建、操作JsonNode对象。

示例1:创建简单JsonNode

@Test
public void testJackJsonTreeModelExample(){// 创建 ObjectMapper 实例ObjectMapper mapper = new ObjectMapper();// 创建并初始化各类型 JsonNode 实例ObjectNode personNode = mapper.createObjectNode();personNode.put("name", "小凡");personNode.put("age", 18);ArrayNode hobbiesNode = mapper.createArrayNode();hobbiesNode.add("写代码").add("看书").add("打豆豆");personNode.set("hobbies", hobbiesNode);// 输出构建的 JSON 字符串System.out.println(personNode.toString());
}
//输出
{"name":"小凡","age":18,"hobbies":["写代码","看书","打豆豆"]}

上述代码首先创建了一个ObjectMapper实例,它是JackJson的核心工具类,负责序列化和反序列化工作。接着,我们创建了一个ObjectNode代表JSON对象,设置了"name"和"age"两个属性。然后创建了一个ArrayNode存储爱好列表,并将其添加到personNode中。最后,打印输出构建的JSON字符串。

示例2:从JSON字符串反序列化为JsonNode

@Test
public void testJackJsonTreeModelExample2() throws JsonProcessingException {String jsonInput = "{\"name\":\"小凡\",\"age\":18,\"hobbies\":[\"写代码\",\"看书\",\"打豆豆\"]}";ObjectMapper mapper = new ObjectMapper();JsonNode rootNode = mapper.readTree(jsonInput);System.out.println(rootNode.get("name").asText());System.out.println(rootNode.get("age").asInt());System.out.println(rootNode.get("hobbies").get(0).asText());System.out.println(rootNode.get("hobbies").get(1).asText());System.out.println(rootNode.get("hobbies").get(2).asText());
}
//输出
小凡
18
写代码
看书
打豆豆

在此示例中,我们首先定义了一个JSON字符串。然后使用ObjectMapperreadTree()方法将其反序列化为JsonNode。接下来,通过调用.get(key)方法访问对象属性或数组元素,并使用.asText().asInt()等方法获取其值。

8.3 利用JackJson树模型进行深度查询、修改、合并等操作

上面给出的两个案例属于入门级操作,我们学会后可以接着进行一些高级操作

@Test
public   void testJsonManipulationExample() throws JsonProcessingException {String JSON_STRING = "{\"name\":\"小凡\",\"age\":18,\"hobbies\":[\"写代码\",\"看书\",\"打豆豆\"]}";ObjectMapper mapper = new ObjectMapper();// 将JSON字符串转换为JsonNode对象JsonNode rootNode = mapper.readTree(JSON_STRING);// **深度查询**// 查询"年龄"int age = rootNode.get("age").asInt();System.out.println("Age: " + age);// 查询第一个兴趣爱好String firstHobby = rootNode.get("hobbies").get(0).asText();System.out.println("First hobby: " + firstHobby);// **修改**// 修改年龄为20((ObjectNode) rootNode).put("age", 20);// 添加新的兴趣爱好:"旅行"((ArrayNode) rootNode.get("hobbies")).add("旅行");// **合并**// 假设有一个新的JSON片段要与原数据合并String additionalJson = "{\"address\":\"北京市\",\"job\":\"程序员\"}";JsonNode additionalNode = mapper.readTree(additionalJson);// 使用ObjectNode#setAll方法将新节点中的键值对合并到原始节点中((ObjectNode) rootNode).setAll((ObjectNode) additionalNode);// 打印更新后的JSON字符串System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode));
}
//输出
Age: 18
First hobby: 写代码
{"name" : "小凡","age" : 20,"hobbies" : [ "写代码", "看书", "打豆豆", "旅行" ],"address" : "北京市","job" : "程序员"
}

九、Jackson注解使用

9.1 序列化反序列化通用注解
9.1.1 @JsonIgnore

@JsonIgnore 用于在序列化或反序列化过程中忽略某个属性

① 定义实体类Person

public class Person {private String name;@JsonIgnore // 添加此注解以忽略 password 字段private String password;// 构造器、getter/setter 方法等...
}

使用示例

@Test
public void testJsonIgnore() throws Exception{Person person = new Person("小凡", "123456");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(person);
}
//输出
{"name": "小凡"
}

③ 详细解释

  • @JsonIgnore 注解直接放在属性声明前,如 private String password; 行上方。

  • 当 Person 类的对象被序列化为 JSON 时,password 属性将不会出现在生成的 JSON 字符串中

  • 同样地,在反序列化过程中,如果 JSON 数据中包含 password 字段,Jackson 在解析时会自动忽略它,不会尝试将其值设置到对应的 Person 对象属性上。

9.1.2 @JsonIgnoreProperties

@JsonIgnore 注解相比,@JsonIgnoreProperties 用于批量指定在序列化或反序列化过程中应忽略的属性列表,特别适用于应对不明确或动态变化的输入 JSON 中可能存在但不应处理的额外字段

① 定义实体类Person

希望同时忽略 password 和 socialSecurityNumber 两个敏感属性

@JsonIgnoreProperties({"password", "socialSecurityNumber"})
public class Person {private String name;private String password;private String socialSecurityNumber;// 构造器、getter/setter 方法等...
}

② 使用示例

@Test
public void testJsonIgnoreProperties() throws Exception{Person person = new Person("小凡", "123456","233535");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(person);
}
//输出
{"name": "小凡"
}

③ 详细解释

  • @JsonIgnoreProperties 注解放置在类定义的开始处,作为类级别的注解。

  • 注解内通过一个字符串数组参数列举出要忽略的属性名。在这个例子中,{"password", "socialSecurityNumber"} 指定了 password 和 socialSecurityNumber 两个属性在序列化和反序列化时应被忽略。

  • 序列化 Person 对象时,生成的 JSON 字符串将不包含 password 和 socialSecurityNumber 属性。与前面 @JsonIgnore 示例类似,JSON 输出仅包含未被忽略的 name 属性:

{"name": "小凡"
}

  • 反序列化时,即使输入的 JSON 数据中包含了 password 或 socialSecurityNumber 字段,Jackson 也会忽略它们,不会尝试将这些字段的值填充到相应的 Person 对象属性中。

④ @JsonIgnoreProperties 还有一个额外功能

@JsonIgnoreProperties有个可选的属性 ignoreUnknown,用于控制是否忽略 JSON 中存在但 Java 类中没有对应的未知属性。若设置为 true,则在反序列化时遇到未知属性时会自动忽略,避免抛出异常

@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {// ...
}

9.1.3 @JsonIgnoreType

@JsonIgnoreType 注解在 Jackson 库中用于指示整个类在序列化或反序列化过程中应当被忽略。这适用于那些由于某种原因(如敏感信息、内部细节等)不需要或不应该被 JSON 化处理的类

定义CreditCardDetails 实体类

// 标记该类在序列化和反序列化时应被忽略
@JsonIgnoreType
public class CreditCardDetails {private String cardNumber;private String cvv;private String expirationDate;// 构造器、getter/setter 方法等...
}

定义Customer 类

Customer 类,它有一个 creditCardDetails 属性引用上述 CreditCardDetails 类型的对象:

public class Customer {private String customerId;private String name;private CreditCardDetails creditCardDetails;// 构造器、getter/setter 方法等...
}

③ 使用示例

public void testJsonIgnoreType() throws JsonProcessingException {Customer customer = new Customer("CUST001", "John Doe", new CreditCardDetails("1234567890123456", "123", "2024-12"));ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(customer);
}
//输出
{"customerId": "CUST001","name": "John Doe"
}

④ 详细解释

  • @JsonIgnoreType 注解放置在需要忽略的类定义前,作为类级别的注解。

  • 当 Customer 类对象被序列化为 JSON 时,所有 CreditCardDetails 类型的属性(如 customer.creditCardDetails)都会被完全忽略,不会出现在生成的 JSON 字符串中。例如:

在此例中,生成的 json 字符串将不含 creditCardDetails 部分,仅包含 customerId 和 name

{"customerId": "CUST001","name": "John Doe"
}

同理,在反序列化过程中,如果 JSON 数据中包含 CreditCardDetails 类型的嵌套结构,Jackson 解析时会自动忽略这部分内容,不会尝试创建或填充对应的 CreditCardDetails 对象

9.1.4 @JsonAutoDetect

@JsonAutoDetect 用于自定义类的属性(包括字段和 getter/setter 方法)在序列化和反序列化过程中的可见性规则。默认情况下,Jackson 只使用 public 的字段和 public 的 getter/setter 方法。通过使用 @JsonAutoDetect,你可以根据需要调整这些规则,以适应不同类的设计和数据模型。

① 定义实体类Employee

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE,   // 不使用字段getterVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC, // 允许 protected 和 public 的 gettersetterVisibility = JsonAutoDetect.Visibility.ANY,   // 允许任意访问权限的 setterisGetterVisibility = JsonAutoDetect.Visibility.DEFAULT,  // 默认行为(public)creatorVisibility = JsonAutoDetect.Visibility.DEFAULT) // 默认行为(public)
public class Employee {protected String id;String department; // package-private 字段// 非标准命名的 getterpublic String getIdentification() {return id;}// 非标准命名的 setterpublic void setIdentification(String id) {this.id = id;}//...标准getter setter}

使用示例

@Test
public  void testJsonAutoDetect() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();Employee employee = new Employee();employee.setId("E001");employee.setDepartment("Sales");String json = mapper.writeValueAsString(employee);System.out.println(json);
}
//输出
{"identification": "E001","department": "Sales"
}

③ 详细解释

  • 在上述 Employee 类的例子中:fieldVisibility = JsonAutoDetect.Visibility.NONE 指定不使用任何字段,意味着即使有 public 字段,也不会被 Jackson 处理。getterVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC 允许 Jackson 使用 protected 和 public 的 getter 方法。setterVisibility = JsonAutoDetect.Visibility.ANY 指定可以使用任意访问权限的 setter 方法。isGetterVisibility 和 creatorVisibility 使用默认行为,即只处理 public 的 is-getter 方法和构造函数。

  • 因为我们将 id 字段的 getter 和 setter 设为了非标准命名(getIdentification() 和 setIdentification()),且指定了 getterVisibility = JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC,所以 Jackson 能正确识别并处理这两个方法,尽管它们不是标准的 get 前缀命名。

9.1.5 @JsonProperty

用于指定类的属性在序列化和反序列化成 JSON 时所对应的键名

Book 实体类

假设有一个 Book 类,其中包含 title 和 yearPublished 字段。我们希望在序列化和反序列化时,将 yearPublished 字段以 publishedYear 作为 JSON 键名。可以使用 @JsonProperty 注解进行重命名:

public class Book {private String title;@JsonProperty("publishedYear") // 重命名 yearPublished 字段为 publishedYearprivate int yearPublished;// 构造器、getter/setter 方法等...
}

使用示例:

现在创建一个 Book 对象并序列化为 JSON:

public void testJsonProperty() throws Exception {Book book = new Book();book.setTitle("小凡编程语录");book.setYearPublished(1951);ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(book);System.out.println(json);
}
//输出
{"title": "小凡编程语录","publishedYear": 1951
}

详细解释

在本例中,@JsonProperty("publishedYear") 表明 yearPublished 字段在 JSON 中应称为 publishedYear

反序列化时,当遇到 JSON 中的 publishedYear 键时,Jackson 会知道应该将其值赋给 Book 类的 yearPublished 字段。

9.1.6 @JsonFormat

用于指定日期、时间、日期时间以及其他数值类型在序列化和反序列化为 JSON 时的格式

① 创建 Student 类

public class Student {// 其他属性...// 使用 @JsonFormat 注解的 LocalDate 属性@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")private LocalDate birthday;// 构造器、getter、setter 等...
}

使用示例

注:Jackson默认不支持Java 8的日期时间类型java.time.LocalDate,如果使用jdk8需要引入如下依赖.

<dependency><groupId>com.fasterxml.jackson.datatype</groupId><artifactId>jackson-datatype-jsr310</artifactId><version>最新版本号</version> <!-- 替换为当前最新的稳定版本 -->
</dependency>

除了引入以来外,还需要确保在使用Jackson进行序列化和反序列化时,注册JavaTimeModule

mapper.registerModule(new JavaTimeModule());

@Test
public void testJsonFormat() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper(); // 创建 Jackson 的 ObjectMapper 实例mapper.registerModule(new JavaTimeModule());// 序列化示例Student student = new Student();student.setName("小凡");student.setAge(18);student.setBirthday(LocalDate.of(1990,1,1)); // 设置用户的出生日期String json = mapper.writeValueAsString(student); // 将用户对象转换为 JSON 字符串System.out.println(json); // 输出序列化后的 JSON 数据// 反序列化示例String inputJson = "{\"birthday\":\"1990-01-01\"}";Student deserializedUser = mapper.readValue(inputJson, Student.class); // 从 JSON 字符串反序列化为 User 对象System.out.println(deserializedUser.getBirthday()); // 输出反序列化后获得的出生日期
}
//输出
{"name":"小凡","age":18,"birthday":"1990-01-01"}
1990-01-01

详细解释

@JsonFormat 注解在 Jackson 中被用来精确控制日期/时间类型的属性在 JSON 序列化和反序列化过程中的格式。通过给定合适的 shape 和 pattern 参数,可以确保日期数据在 Java 类型与 JSON 文本之间准确无误地转换。

9.2 序列化注解

9.2.1 @JsonInclude

用于控制对象在序列化过程中包含哪些属性。它可以防止空或特定值的字段被序列化到JSON输出中,从而帮助您精简JSON数据结构,减少不必要的传输量或避免向客户端暴露不必要的信息

定义PersonInclude实体类

@JsonInclude(JsonInclude.Include.NON_NULL)
public class PersonInclude {/*** 姓名字段,由于未指定@JsonInclude注解,因此继承类级别的NON_NULL策略*/private String name;/*** 职业字段,显式指定为仅在非空时才包含在序列化结果中*/@JsonInclude(JsonInclude.Include.NON_EMPTY)private String occupation;/*** 兴趣爱好列表,遵循类级别的NON_NULL策略*/private List<String> hobbies;// 构造函数、getter/setter等省略...}

使用示例

@Test
public void testJsonInclude() throws JsonProcessingException {PersonInclude personFull = new PersonInclude();personFull.setName("小凡");personFull.setOccupation("程序员");personFull.setHobbies(Arrays.asList("编程","看书","打豆豆"));PersonInclude personPartial = new PersonInclude();personPartial.setName(null);personPartial.setOccupation("保洁员");ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(personFull);System.out.println(json);String json1 = mapper.writeValueAsString(personPartial);System.out.println(json1);}
//输出
{"name":"小凡","occupation":"程序员","hobbies":["编程","看书","打豆豆"]}
{"occupation":"保洁员"}

③ 详细解释

  • 测试用例1:序列化后,JSON只包含nameoccupationhobbies字段都不为空,所以都显示出来

  • 测试用例2:创建了一个部分字段为null或空的PersonInclude实例。为空的不显示

9.2.2 @JsonGetter

用于告诉Jackson,应该通过调用getter方法而不是通过直接字段访问来获取某个字段值

创建PersonGetter实体类

public class PersonGetter {private String firstName;private String lastName;// 使用 @JsonGetter 定义一个方法,该方法将在序列化时作为 "fullName" 属性的值返回@JsonGetter("fullName")public String getFullName() {return this.firstName + " " + this.lastName;}// 构造函数和其他常规setter/getter方法
}

使用示例

@Test
public void testJsonGetter() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper(); // 创建 Jackson 的 ObjectMapper 实例PersonGetter person = new PersonGetter("张", "小凡");// 创建一个 Person 对象String json = mapper.writeValueAsString(person); // 将 Person 对象序列化为 JSON 字符串System.out.println(json); // 输出序列化后的 JSON
}
//输出
{"firstName":"张","lastName":"小凡","fullName":"张 小凡"}

@JsonGetter 注解成功地将 getFullName() 方法的结果映射到 JSON 对象中的 "fullName" 属性。

9.2.3 @JsonAnyGetter

用于标记一个方法,获取除已知属性外的所有其他键值对。这些键值对通常存储在一个 Map 结构中,

以便将它们作为一个附加的对象进行序列化。

① 创建CustomData实体类

@Data
public class CustomData {private final Map<String, Object> additionalProperties = new HashMap<>();// 使用 @JsonAnyGetter 定义一个方法,该方法将在序列化时返回所有额外属性@JsonAnyGetterpublic Map<String, Object> getAdditionalProperties() {return additionalProperties;}// 提供方法来添加或修改额外属性public void addProperty(String key, Object value) {additionalProperties.put(key, value);}
}

使用示例

 @Test
public void testJsonAnyGetter() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper(); // 创建 Jackson 的 ObjectMapper 实例CustomData data = new CustomData();data.addProperty("key1", "value1");data.addProperty("key2", 42);data.addProperty("key3", "value3");String json = mapper.writeValueAsString(data); // 将 CustomData 对象序列化为 JSON 字符串System.out.println(json); // 输出序列化后的 JSON
}
//输出
{"key1":"value1","key2":42,"key3":"value3"}

@JsonAnyGetter 注解的主要作用如下:

  • 动态属性支持:通过在返回 Map 的方法上使用 @JsonAnyGetter,您可以将一个对象的动态属性集合序列化为 JSON 对象的多个键值对。这些属性可能是在运行时添加的,或者基于某些条件动态生成的。

  • 简化结构:避免为每个可能的动态属性单独声明字段和 getter/setter。只需维护一个 Map,即可处理任意数量和类型的额外属性。

  • 兼容性与灵活性:当需要与未知或未来可能变化的数据结构交互时,@JsonAnyGetter 可确保 JSON 表示能够容纳未预定义的属性,从而提高系统的兼容性和适应性。

9.2.4 @JsonPropertyOrder

用于指定类中属性在序列化为 JSON 时的排序规则

创建OrderPerson 实体类

public class OrderPerson {@JsonProperty("firstName")private String givenName;@JsonProperty("lastName")private String familyName;// 构造函数和其他常规setter/getter方法
}

使用示例

 @Test
public void testJsonPropertyOrder() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper(); // 创建 Jackson 的 ObjectMapper 实例OrderPerson person = new OrderPerson("John", "Doe"); // 创建一个 OrderedPerson 对象String json = mapper.writeValueAsString(person); // 将 OrderedPerson 对象序列化为 JSON 字符串System.out.println(json); // 输出序列化后的 JSON
}
//输出
{"firstName":"John","lastName":"Doe"}

@JsonPropertyOrder 注解按照指定顺序("lastName""firstName")对 JSON 对象的属性进行了排序。

9.2.5 @JsonRawValue

用于标记一个字段或方法返回值,指示Jackson在序列化时应将其原始值视为未经转义的 JSON 字符串,并直接嵌入到输出的 JSON 文档中。即使所标记的值包含 JSON 特殊字符(如双引号、反斜杠等),也不会对其进行转义

① 创建一个包含 @JsonRawValue 注解的类

public class RawJsonValueExample {private String normalProperty = "这是一个正常字符串";// 使用 @JsonRawValue 标记 rawJsonProperty,使其内容被视为未经转义的 JSON 值@JsonRawValueprivate String rawJsonProperty = "{\"key\": \"value\", \"array\": [1, 2, 3]}";// 构造函数和其他常规setter/getter方法
}

使用示例

@Test
public void testJsonRawValue() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper(); // 创建 Jackson 的 ObjectMapper 实例RawJsonValueExample example = new RawJsonValueExample(); // 创建一个 RawJsonValueExample 对象String json = mapper.writeValueAsString(example); // 将 RawJsonValueExample 对象序列化为 JSON 字符串System.out.println(json); // 输出序列化后的 JSON
}
//输出
{"normalProperty":"这是一个正常字符串","rawJsonProperty":{"key": "value", "array": [1, 2, 3]}}

rawJsonProperty 的值并未被转义,而是作为一个完整的 JSON 对象直接嵌入到父 JSON 文档中。

当您需要在 JSON 对象中嵌入另一段 JSON 文本时,使用 @JsonRawValue 可以确保这段文本以未经转义的形式出现在输出的 JSON 中,保持其原有的 JSON 结构。

9.2.6 @JsonValue

用于标记一个方法或字段,Jackson在序列化该类实例时,直接使用该方法的返回值或字段的值作为整个对象的 JSON 表示,而非按照类的常规属性进行序列化

① 创建JsonValueExample

public class JsonValueExample {private LocalDate date;private String formattedDate;@JsonValuepublic String asJsonString() {return "{\"date\":\"" + date.toString() + "\",\"formatted\":\"" + formattedDate + "\"}";}// 构造函数和其他常规setter/getter方法
}

② 使用示例

@Test
public void testJsonValue() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();JsonValueExample example = new JsonValueExample();example.setDate(LocalDate.of(2024,4,6));example.setFormattedDate("yyyy-MM-dd");String json = mapper.writeValueAsString(example);System.out.println(json);
}
//输出
"{\"date\":\"2024-04-06\",\"formatted\":\"yyyy-MM-dd\"}"

在 asJsonString() 方法上应用注解,指示序列化时应将该方法的返回值作为整个对象的 JSON 表达,忽略类中其他的属性

9.2.7 @JsonSerialize

于指定类、字段或方法在序列化过程中使用的自定义序列化逻辑

① 创建一个包含 @JsonSerialize 注解的类及其自定义序列化器

public class BooleanSerializer extends JsonSerializer<Boolean> {@Overridepublic void serialize(Boolean aBoolean, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if(aBoolean){jsonGenerator.writeNumber(1);} else {jsonGenerator.writeNumber(0);}}
}public class PersonSerializer {public long   personId = 0;public String name     = "John";@JsonSerialize(using = BooleanSerializer.class)public boolean enabled = false;// 构造函数和其他常规setter/getter方法
}

使用示例

@Test
public void testJsonSerialize() throws JsonProcessingException {PersonSerializer person = new PersonSerializer();person.setName("小凡");person.setPersonId(1001);person.setEnabled(true);ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(person);System.out.println(json);
}
//输出
{"personId":1001,"name":"小凡","enabled":1}

通过上面代码测试我们可以看到,enabled被序列化为1

9.3 反序列化注解
9.3.1 @JsonSetter

用于标记一个方法或字段,指示 Jackson 在反序列化过程中应如何设置该属性的值

创建PersonSetter 类

public class PersonSetter {@JsonSetter("first_name")private String firstName;@JsonSetter("last_name")private String lastName;// 其他getter setter toString方法省略...
}

使用示例

@Test
public void testJsonSetter() throws JsonProcessingException {String jsonNormal = "{\"first_name\":\"张\", \"last_name\":\"小凡\"}";ObjectMapper mapper = new ObjectMapper();PersonSetter person = mapper.readValue(jsonNormal, PersonSetter.class);System.out.println(person);
}
//输出
PersonSetter(firstName=张, lastName=小凡)

@JsonSetter 注解提供了灵活的方式来定制Jackson在反序列化期间如何将JSON数据映射到Java对象的属性

9.3.2 @JsonAnySetter

用于处理反序列化过程中遇到的未知或额外的 JSON 键值对。当一个对象的JSON表示中包含无法直接映射到已声明属性的键时,这个注解可以帮助捕获并存储这些额外的数据

① 定义带有 @JsonAnySetter 注解的类

@ToString
public class CustomObject {private String knownProperty;private Map<String, Object> additionalProperties = new HashMap<>();// 已知属性的setter方法public void setKnownProperty(String knownProperty) {this.knownProperty = knownProperty;}// 获取已知属性的getter方法省略.../*** @JsonAnySetter注解方法,用于处理反序列化过程中遇到的所有未知属性。** @param key   未知属性的键* @param value 未知属性的值*/@JsonAnySetterpublic void addAdditionalProperty(String key, Object value) {additionalProperties.put(key, value);}// 提供访问额外属性的方法public Map<String, Object> getAdditionalProperties() {return additionalProperties;}
}

使用示例

@Test
public void testJsonAnySetter() throws JsonProcessingException {String json ="{\"knownProperty\":\"expectedValue\",\"extraField1\":\"someValue\",\"extraField2\":42,\"nestedObject\":{\"key\":\"value\"}}";ObjectMapper mapper = new ObjectMapper();CustomObject customObject = mapper.readValue(json, CustomObject.class);System.out.println(customObject);
}
//输出
CustomObject(knownProperty=expectedValue, additionalProperties={extraField1=someValue, nestedObject={key=value}, extraField2=42})

@JsonAnySetter注解来应对JSON反序列化过程中可能出现的未知属性,确保所有数据都能被妥善处理和保留。这种机制特别适用于需要兼容动态或扩展性较强的JSON输入场景。

9.3.3 @JsonCreator

用于标记一个构造器、静态工厂方法或实例方法,使其成为反序列化过程中创建对象实例的入口点。这个注解帮助 Jackson 确定如何根据 JSON 数据构建相应的 Java 对象。

① 定义带有 @JsonCreator 注解的类

public class AddressCreator {private  String street;private  int number;private  String city;// 构造器上使用@JsonCreator注解,指示Jackson使用此构造器反序列化JSON@JsonCreatorpublic AddressCreator(@JsonProperty("street") String street,@JsonProperty("number") int number,@JsonProperty("city") String city) {this.street = street;this.number = number;this.city = city;}// getter setter toString方法省略...
}

② 使用示例

@Test
public void testCreateor() throws JsonProcessingException {String json ="{\"street\":\"呈贡区\",\"number\":123,\"city\":\"昆明\"}";ObjectMapper mapper = new ObjectMapper();AddressCreator addressCreator = mapper.readValue(json, AddressCreator.class);System.out.println(addressCreator);
}
//输出
AddressCreator(street=呈贡区, number=123, city=昆明)

9.3.4 @JacksonInject

用于在反序列化过程中自动注入依赖项或附加信息到目标对象。通常用于处理那些不能直接从 JSON 数据中获取、但又希望在反序列化完成后立即可用的信息

① 定义带有 @JacksonInject 注解的类

public class UserInject {private String name;private String email;// @JacksonInject注解在字段上,指示Jackson在反序列化过程中注入特定值@JacksonInject("defaultEmail")private String defaultEmail;// 构造器和getter setter toString方法省略...
}

使用示例

@Test
public void testJacksonInject() throws JsonProcessingException {// 设置可注入的值InjectableValues injectables = new InjectableValues.Std().addValue("defaultEmail", "xiaofan@example.com");// 创建ObjectMapper并配置注入值ObjectMapper mapper = new ObjectMapper().setInjectableValues(injectables);String json = "{\"name\":\"小凡\"}";// 反序列化时,defaultEmail字段会被自动注入指定值UserInject userInject = mapper.readValue(json, UserInject.class);System.out.println("Name: " + userInject.getName());System.out.println("Email: " + userInject.getEmail());System.out.println("Default Email: " + userInject.getDefaultEmail());
}
//输出
Name: 小凡
Email: null
Default Email: xiaofan@example.com

@JacksonInject 注解在Jackson反序列化过程中用于引入外部依赖或默认值,使得这些信息能够在反序列化完成后立即可用

9.3.5 @JsonDeserialize

用于在反序列化过程中指定自定义的反序列化器来处理某个字段或类的特殊逻辑

自定义反序列化器

public class BooleanDeserializer extends JsonDeserializer<Boolean> {@Overridepublic Boolean deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {String text = jsonParser.getText();if("0".equals(text)) {return false;}return true;}
}

② @JsonDeserialize注解添加到要为其使用自定义反序列化器的字段

public class PersonDeserialize {public long    id;public String  name;@JsonDeserialize(using = BooleanDeserializer.class)public boolean enabled = false;//构造器和getter setter toString方法省略...
}

使用示例

{"id":1001,"name":"小凡","enabled":1}

@Test
public void testJsonDeserialize() throws JsonProcessingException {String json ="{\"id\":1001,\"name\":\"小凡\",\"enabled\":1}";ObjectMapper mapper = new ObjectMapper();PersonDeserialize personDeserialize = mapper.readValue(json, PersonDeserialize.class);System.out.println(personDeserialize);
}
//输出
PersonDeserialize(id=1001, name=小凡, enabled=true)

我们json字符串中enabled的值是1,最终反序列化成PersonDeserialize 对象后值变成了ture

本期内容到此就结束了,希望对你有所帮助。我们下期再见 (●'◡'●)

文章转载自:xiezhr

原文链接:https://www.cnblogs.com/xiezhr/p/18119893

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

相关文章:

轻松上手Jackjson(珍藏版)

写在前面 虽然现在市面上有很多优秀的json解析库&#xff0c;但 Spring默认采用Jackson解析Json。 本文将通过一系列通俗易懂的代码示例&#xff0c;带你逐步掌握 Jackson 的基础用法、进阶技巧以及在实际项目中的应用场景。 一、Jackjson简介 Jackson 是当前用的比较广泛的&a…...

Pytorch数据结构:Tensor(张量)及其维度和数据类型

文章目录 Tensor基础1.1、Tensor的维度&#xff08;Dimensions&#xff09;1.1.1、举例说明1.1.2、高维Tensor 1.2、.dim()和.size()方法1.2.1、.dim()方法1.2.2、.size()方法1.2.3、.shape属性1.2.3、示例代码1.2.3.1、一维Tensor1.2.3.2、二维Tensor1.2.3.3、三维Tensor 1.3、…...

【THM】Protocols and Servers 2(协议和服务器 2

介绍 协议和服务器房间涵盖了许多协议: 远程登录HTTP协议文件传输协议邮件传输协议POP3IMAP实现这些协议的服务器会受到不同类型的攻击。仅举几例,请考虑: 嗅探攻击(网络数据包捕获)中间人 ( MITM ) 攻击密码攻击(身份验证攻击)漏洞从安全的角度来看,我们始终需要思考…...

阿里云服务器可以干什么?阿里云服务器主要用途是干嘛的?

阿里云服务器可以干嘛&#xff1f;能干啥你还不知道么&#xff01;简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;阿里云百科aliyunbaike.com整理阿里云服务器的用途&#xff1a; 阿里云服务器活动 aliyunbaike.com…...

LeetCode hoot100-22

160. 相交链表给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。这道题几分钟就写出来了。应该是几年前做过&#xff0c;这种思想还能一直记得。所以算法题是不会白做的。 我的…...

蓝桥杯 经验技巧篇

1. 注意事项 &#x1f468;‍&#x1f3eb; 官方通知 &#x1f468;‍&#x1f3eb; 资料文档 时间&#xff1a;4月13日 9:00~13:00 &#xff08;时长 4小时&#xff09;物品 准考证&#xff08;赛前一周开放下载&#xff0c;自行打印&#xff09;学生证身份证笔、水、外套&a…...

QMC5883芯片I2C驱动开发指南

这个芯片纯国产挺好用的&#xff0c;电路很好设计&#xff0c;我这垃圾焊功&#xff0c;纯手焊&#xff0c;&#xff0c;居然能用。 第一部分 硬件连接 画的很简陋&#xff0c;看看就可以了。 第二部分 软件驱动 I2C的具体时序实现需要自己搞定&#xff01;&#xff01; 2…...

缓存击穿以及解决方案

1.定义 缓存击穿问题也叫热点Key问题&#xff0c;就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 问题描述&#xff1a;假设线程1在查询缓存之后&#xff0c;本来应该去查询数据库&#xff0c;然后把…...

【电路笔记】-逻辑非门

逻辑非门 文章目录 逻辑非门1、概述2、晶体管逻辑非门3、六角施密特反相器逻辑非门是所有逻辑门中最基本的,通常称为反相缓冲器或简称为反相器。 1、概述 反相非门是单输入器件,其输出电平通常为逻辑电平“1”,当其单个输入为逻辑电平“1”时,输出电平变为“低”至逻辑电平…...

vue-element-admin vue3版本搭建

要搭建一个基于Vue 3版本的vue-element-admin项目&#xff0c;你可以按照以下步骤进行&#xff1a; 首先&#xff0c;确保你的开发环境已经安装了Node.js和npm。Node.js是一个JavaScript运行环境&#xff0c;而npm则是Node.js的包管理器&#xff0c;它们将帮助你安装和管理Vue…...

大话设计模式——11.桥接模式(Bridge Pattern)

简介 将抽象部分与它的实现部分分离&#xff0c;使它们可以独立变化。 UML图&#xff1a; 应用场景&#xff1a; 系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性不想使用继承导致系统类的个数急剧增加某个类存在多个变化维度使用继承方式容易出现类的膨胀 示例…...

新概念英语1:Lesson 25学习笔记

新概念英语1&#xff1a;Lesson 25学习笔记 There is a refrigerator in the kitchen There be句型是英语中一个常用的表达方法&#xff0c;它表示某个地方或某个情况存在某种事物或人。 there是引导词&#xff0c;本身无意义 句型基本上就是Therebe动词主语地点/时间 be动…...

Java 8 内存管理原理解析及内存故障排查实践

介绍Java8虚拟机的内存区域划分、内存垃圾回收工作原理解析、虚拟机内存分配配置&#xff0c;介绍各垃圾收集器优缺点及场景应用、实践内存故障场景排查诊断&#xff0c;方便读者面临内存故障时有一个明确的思路和方向。 一、背景 Java是一种流行的编程语言&#xff0c;可以在不…...

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之RTE模块配置详解(上)

RTE模块配置详解 - 上 一、RTE模块配置实操1.1 打开RTE模块1.2 RTE模块错误消除在这里插入图片描述 这里我们利用工具的自动处理功能。二、Configurator工具Validation总结本节我们就手把手详解RTE配置实现,其实也没有什么过多的操作。。。这个模块更多是工具自动处理的。 一、…...

小米汽车su7全色系展示源码

源码简介 小米汽车全色系展示源码&#xff0c;小米汽车su7全色系展示源码 安装教程 纯HTML&#xff0c;直接将压缩包上传网站目录解压即可 首页截图 源码下载 小米汽车su7全色系展示源码-小8源码屋源码简介 小米汽车全色系展示源码&#xff0c;小米汽车su7全色系展示源码 …...

钉钉事件订阅前缀树算法gin框架解析

当钉钉监测到发生一些事件&#xff0c;如下图 此处举例三个事件user_add_org、user_change_org、user_leave_org&#xff0c;传统的做法是&#xff0c;我们写三个if条件&#xff0c;类似下图 这样字符串匹配效率比较低&#xff0c;于是联想到gin框架中的路由匹配算法&#xff0…...

React18从入门到实战

文章目录 一、React环境的搭建二、项目文件的介绍&#xff08;1&#xff09;package.json&#xff0c;他是项目存放依赖包的地方&#xff0c;里面包括了一些项目核心包及下载的其他插件包&#xff08;2&#xff09;src文件夹是项目源码目录&#xff0c;平时开发页面就在其中&am…...

【漏洞复现】某科技X2Modbus网关多个漏洞

漏洞描述 最近某科技X2Modbus网关出了一个GetUser的信息泄露的漏洞,但是经过审计发现该系统80%以上的接口均是未授权的,没有添加相应的鉴权机制,以下列举多个未授权接口以及获取相关敏感信息的接口。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律…...

专业140+总410+国防科技大学831信号与系统考研经验国防科大电子信息与通信,真题,大纲,参考书。

应群里同学要求&#xff0c;总结一下我自己的复习经历&#xff0c;希望对大家有所借鉴&#xff0c;报考国防科技大学&#xff0c;专业课831信号与系统140&#xff0c;总分410&#xff0c;大家以前一直认为国防科技大学时军校&#xff0c;从而很少关注这所军中清华&#xff0c;现…...

【Linux】进程管理(2):进程控制

一、进程创建&#xff1a;fork函数 我们在命令行中输入man fork 即可得到fork函数的函数接口的函数的使用方法。 我们可以看到&#xff0c;fork函数位于man手册的第2部分&#xff0c;由于第2部分通常是用于描述系统调用和库函数&#xff0c;所以我们可以了解到fork函数实际是一…...

组合数(费马小定理, 快速幂)

给定 n 组询问&#xff0c;每组询问给定两个整数 a&#xff0c;b&#xff0c;请你输出 Cbamod(1097)的值。 输入格式 第一行包含整数 n。 接下来 n 行&#xff0c;每行包含一组 a 和 b。 输出格式 共 n 行&#xff0c;每行输出一个询问的解。 数据范围 1≤n≤10000, 1≤…...

VMware Esxi安装群辉系统

群晖的网络存储产品具有强大的操作系统&#xff0c;提供了各种应用程序和服务&#xff0c;包括文件共享、数据备份、多媒体管理、远程访问等。用户可以通过简单直观的界面来管理他们的存储设备&#xff0c;并且可以根据自己的需求扩展设备的功能。总的来说&#xff0c;群晖的产…...

arm交叉编译器工具

下载地址&#xff1a; Builds & Downloads | Linaro 进入首页后&#xff0c;点击" GNU Toolchain Integration Builds" 有以下版本&#xff1a; 根据自己的选择下载对应的版本&#xff0c;本例选择14.0-2023.06-1 根据板端对应的版本选择相应的下载 比如下载3…...

Dajngo -- 表单

表单 form 此后的 app 名以 polls 为例 <h1>{{ question.question_text }}</h1>{% if error_message %} <p> <strong>{{ error_message }}</strong> </p> {% endif %}<form action"{% url polls:vote question.id %}" method…...

NIO基础知识

在学习Netty之前先要学习一下NIO相关的知识&#xff0c;因为Netty是基于NIO搭建的一套网络编程框架。 一. NIO 基础 non-blocking io 非阻塞 IO 1. 三大组件 1.1 Channel & Buffer channel 有一点类似于 stream&#xff0c;它就是读写数据的双向通道&#xff0c;可以从…...

C语言正则表达式 regnext regreplace regreplaceAll

由于C语言的正则表达式API相对比较简易.默认API只有regcomp/regerror/regexec/regfree这些函数.相对于其他的高级语言中正则表达式所所能实现的功能(如:查找/替换)有所欠缺.所以想着自己写下一些需要的函数以备后续需要使用. #ifndef _E_REGEX_INCLUDE #define _E_REGEX_INCLU…...

使用aspose相关包将excel转成pdf 并导出

SpringBoot 项目 基于aspose相关jar包 将excel 转换成pdf 导出 1、依赖的jar包 &#xff0c; jar获取链接 aspose相关三方jar &#xff0c;下载解压后,在项目路径下建一个libs包&#xff0c;然后将下图两个jar 拷贝至刚新建的libs目录中 2、pom.xml中加入maven引入 <depend…...

按关键字搜索商品API接口搜索关键字,显示商品总数,标题,图片,优惠价参数等

按关键字搜索商品API接口通常用于根据关键字搜索商品&#xff0c;并返回商品的相关信息。以下是一个示例&#xff0c;说明如何使用Python调用按关键字搜索商品API接口。 item_search-按关键字搜索淘宝商品 公共参数 API接口请求地址:调用key 名称类型必须描述keyString是调用…...

网络基础知识入门

目录 一、局域网与广域网 1、局域网 2、广域网 二、协议 1、概念 2、协议的理解 3、协议的分层 1、分层 2、OSI七层模型 三、网络传输基本流程 1、报头 2、局域网通信原理 3、跨网络传输流程 四、IP地址和MAC地址 1、IP地址 2、MAC地址 3、两者的区别 一、局域…...

D435i发布的话题学习

参考自https://blog.csdn.net/sinat_16643223/article/details/136406602?spm1001.2014.3001.5502 这里整理一下D435i庞大的topic话题数据。 根据算法来说的话&#xff0c;vins-fusion需要双目灰度图像的话题&#xff1a; camera/infra1/image_rect_raw 和camera/infra2/image…...