轻松上手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文件,文件内容如下
②将字节输入流转换为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文件,内容如下
② 读取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}
而现在的需求升级了,再不创建或修改User
s实体对象的情况下,我们想要得到{"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)
插入新元素。 -
TextNode、IntNode、LongNode、DoubleNode等:分别对应JSON中的字符串、整数、长整数、浮点数等基本类型值。
-
BooleanNode、NullNode:分别对应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字符串。然后使用ObjectMapper
的readTree()
方法将其反序列化为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只包含
name
、occupation
和hobbies
字段都不为空,所以都显示出来 -
测试用例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解析库,但 Spring默认采用Jackson解析Json。 本文将通过一系列通俗易懂的代码示例,带你逐步掌握 Jackson 的基础用法、进阶技巧以及在实际项目中的应用场景。 一、Jackjson简介 Jackson 是当前用的比较广泛的&a…...

Pytorch数据结构:Tensor(张量)及其维度和数据类型
文章目录 Tensor基础1.1、Tensor的维度(Dimensions)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 ) 攻击密码攻击(身份验证攻击)漏洞从安全的角度来看,我们始终需要思考…...

阿里云服务器可以干什么?阿里云服务器主要用途是干嘛的?
阿里云服务器可以干嘛?能干啥你还不知道么!简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等,阿里云百科aliyunbaike.com整理阿里云服务器的用途: 阿里云服务器活动 aliyunbaike.com…...
LeetCode hoot100-22
160. 相交链表给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。这道题几分钟就写出来了。应该是几年前做过,这种思想还能一直记得。所以算法题是不会白做的。 我的…...

蓝桥杯 经验技巧篇
1. 注意事项 👨🏫 官方通知 👨🏫 资料文档 时间:4月13日 9:00~13:00 (时长 4小时)物品 准考证(赛前一周开放下载,自行打印)学生证身份证笔、水、外套&a…...

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

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

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

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

大话设计模式——11.桥接模式(Bridge Pattern)
简介 将抽象部分与它的实现部分分离,使它们可以独立变化。 UML图: 应用场景: 系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性不想使用继承导致系统类的个数急剧增加某个类存在多个变化维度使用继承方式容易出现类的膨胀 示例…...
新概念英语1:Lesson 25学习笔记
新概念英语1:Lesson 25学习笔记 There is a refrigerator in the kitchen There be句型是英语中一个常用的表达方法,它表示某个地方或某个情况存在某种事物或人。 there是引导词,本身无意义 句型基本上就是Therebe动词主语地点/时间 be动…...

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

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

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

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

React18从入门到实战
文章目录 一、React环境的搭建二、项目文件的介绍(1)package.json,他是项目存放依赖包的地方,里面包括了一些项目核心包及下载的其他插件包(2)src文件夹是项目源码目录,平时开发页面就在其中&am…...

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

专业140+总410+国防科技大学831信号与系统考研经验国防科大电子信息与通信,真题,大纲,参考书。
应群里同学要求,总结一下我自己的复习经历,希望对大家有所借鉴,报考国防科技大学,专业课831信号与系统140,总分410,大家以前一直认为国防科技大学时军校,从而很少关注这所军中清华,现…...

【Linux】进程管理(2):进程控制
一、进程创建:fork函数 我们在命令行中输入man fork 即可得到fork函数的函数接口的函数的使用方法。 我们可以看到,fork函数位于man手册的第2部分,由于第2部分通常是用于描述系统调用和库函数,所以我们可以了解到fork函数实际是一…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

SQL注入篇-sqlmap的配置和使用
在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap,但是由于很多朋友看不了解命令行格式,所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习,链接:https://wwhc.lanzoue.com/ifJY32ybh6vc…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...

动态生成element-plus的scss变量;SCSS中实现动态颜色变体生成
文章目录 一、动态css变量1.生成内容2.动态生成css变量2.1新增_color-utils.scss(不推荐)2.2新增_color-utils.scss(推荐)2.3theme.scss引入使用 一、动态css变量 1.生成内容 在我们修改element-plus主题色时候,会自…...

c++ decltype关键字
decltype为类型推导关键字。 示例代码: // decltype也可用于函数模板编程: template<typename T, typename U> auto add(T t, U u) -> decltype(t u) {return t u; }// decltype推导函数返回类型 auto doubleNumFunc(int x) -> decltype(x * 2) {ret…...