Java jackson常用註解彙總

来源:https://www.cnblogs.com/davis12/archive/2023/11/08/17817871.html
-Advertisement-
Play Games

提起 jackson,在日常使用中,由於涉及到各種序列化和反序列化的處理,就不能不提 註解,瞭解註解的常用方式可以極大地方便我們處理序列化,今天分享一些在使用 jackson 中涉及到的註解。 目錄1.@JsonProperty - 欄位命名2.@JsonPropertyOrder - 欄位序列化順 ...


提起 jackson,在日常使用中,由於涉及到各種序列化和反序列化的處理,就不能不提 註解,瞭解註解的常用方式可以極大地方便我們處理序列化,今天分享一些在使用 jackson 中涉及到的註解。

目錄

1.@JsonProperty - 欄位命名

@JsonProperty 註解用於在序列化時按照給定的欄位名命名,在反序列化時,在 json 串中的註解欄位給該欄位設置屬性值。

下麵是註解的簡單示例:

package org.example;

import com.fasterxml.jackson.annotation.JsonProperty;

public class PersonProperty {
    @JsonProperty("first_name")
    private String firstName;

    public PersonProperty() {
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

---
public static void jsonPropertyDemo() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonProperty pp = new PersonProperty();
    pp.setFirstName("Alice");

    String jsonString = null;
    try {
        jsonString = objectMapper.writeValueAsString(pp);
        System.out.println("json property: " + jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        PersonProperty pp1 = objectMapper.readValue(jsonString, PersonProperty.class);
        System.out.println(pp1.getFirstName());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

2.@JsonPropertyOrder - 欄位序列化順序

@JsonPropertyOrder加在類上,用以規定數據序列化時欄位出現的順序。

package org.example;

import com.fasterxml.jackson.annotation.JsonPropertyOrder;

// {"name":"Bob","id":"111","age":25,"phone":"12345678910"}
@JsonPropertyOrder({"name", "id", "age", "phone"}) 
// 沒有定義順序,就按照字典序排列,{"age":25,"id":"111","name":"Bob","phone":"12345678910"}
// @JsonPropertyOrder(alphabetic = true) 
public class PersonPropertyOrder {
    private String id;

    private String name;

    private int age;

    private String phone;

    public PersonPropertyOrder() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }
}

---
public static void jsonPropertyOrder() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonPropertyOrder ppo = new PersonPropertyOrder();
    ppo.setAge(25);
    ppo.setId("111");
    ppo.setName("Bob");
    ppo.setPhone("12345678910");

    String jsonString = null;
    try {
        jsonString = objectMapper.writeValueAsString(ppo);
        System.out.println("json property: " + jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

---

3.@JsonAlias - 欄位別名,反序列化

在數據反序列化時,通過 @JsonAlias 註解來設置欄位的值,只要是 alias中的和欄位本身都可以正常反序列化。

package org.example;

import com.fasterxml.jackson.annotation.JsonAlias;

public class PersonAlias {
    @JsonAlias({"firstName", "personName"})
    private String name;

    public PersonAlias() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
---
public static void jsonAlias() {
    String jsonString1 = "{"name":"Bob"}";
    String jsonString2 = "{"firstName":"Bob"}";
    String jsonString3 = "{"personName":"Bob"}";

    ObjectMapper objectMapper = new ObjectMapper();
    try {
        PersonAlias p1 = objectMapper.readValue(jsonString1, PersonAlias.class);
        PersonAlias p2 = objectMapper.readValue(jsonString2, PersonAlias.class);
        PersonAlias p3 = objectMapper.readValue(jsonString3, PersonAlias.class);

        System.out.printf("p1: %s, p2: %s, p3: %s", p1.getName(),p2.getName(), p3.getName());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

4.@JsonIgnore -序列化時忽略欄位

@JsonIgnore 加在欄位上,用以在序列化時,忽略其,在反序列化時,僅賦值null。

package org.example;

import com.fasterxml.jackson.annotation.JsonIgnore;


public class PersonIgnore {
    private String name;
    @JsonIgnore // 不將其序列化,忽略該欄位
    private String[] hobbies;

    public PersonIgnore() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }
}

---
public static void jsonIgnore() {
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = null;

    try {
        PersonIgnore pi = new PersonIgnore();
        pi.setName("Cathy");
        pi.setHobbies(null);

        jsonString = objectMapper.writeValueAsString(pi);
        System.out.println(jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}    
---

5.@JsonIgnoreProperties - 序列化時忽略某些欄位

@JsonIgnoreProperties 加在類上,用於在序列化時,忽略給定的某些欄位。

package org.example;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties({"age"})
public class PersonIgnoreProperties {
    private String name = "Alice";
    private int age;

    public PersonIgnoreProperties() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
---
public static void jsonIgnoreProperties() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonIgnoreProperties pip = new PersonIgnoreProperties();
    pip.setName("Bob");
    pip.setAge(18);

    try {
        String jsonString = objectMapper.writeValueAsString(pip);
        System.out.println(jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

6.@JsonInclude - 序列化時作用於滿足條件的

@JsonInclude可以加在類上,也可以加在欄位上。該註解表示滿足某些條件(
NON_NULL,
NON_ABSENT,
NON_EMPTY,
NON_DEFAULT,
等)的才能序列化,e.g.如果加在類上,表示只要對象有null 就忽略該對象,加在欄位上,如果欄位是null,則忽略該欄位。

package org.example;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class PersonInclude {
    private int id;

    private String name;
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String[] hobbies;

    public PersonInclude() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }
}
---
public static void jsonInclude() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonInclude pi = new PersonInclude();

    pi.setName("Cathy");
    pi.setId(1111);

    try {
        String jsonString = objectMapper.writeValueAsString(pi);
        System.out.println(jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

7.@JsonFormat - 設置格式,如日期時間等

用於設置時間格式,或者是數字,或者是日期格式。

package org.example;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.LocalDate;
import java.util.Date;

public class PersonFormat {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
    private Date birthDate;

    public PersonFormat() {
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }
}

---
public static void jsonFormat() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonFormat pf = new PersonFormat();
    pf.setBirthDate(new Date());

    try {
        String jsonString = objectMapper.writeValueAsString(pf);
        System.out.println(jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

8.@JacksonInject - 反序列化時註入到 java 對象

該註解用於在數據反序列化時將其他欄位註入進 Java對象。

package org.example;

import com.fasterxml.jackson.annotation.JacksonInject;

import java.time.LocalDate;
import java.time.LocalDateTime;

public class PersonInject {

    private String name;
    
    private int age;
    
    @JacksonInject("responseTime")
    private LocalDateTime responseTime;

    public PersonInject() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public LocalDateTime getResponseTime() {
        return responseTime;
    }

    public void setResponseTime(LocalDateTime responseTime) {
        this.responseTime = responseTime;
    }
}

---

public static void jsonInject() {
    InjectableValues.Std iv = new InjectableValues.Std();
    ObjectMapper objectMapper = new ObjectMapper();
    iv.addValue("responseTime", LocalDateTime.now());

    //將JSON字元串反序列化為java對象
    String jsonString = "{"name":"Alice","age":23}";
    objectMapper.setInjectableValues(iv);

    try {
        PersonInject pi = objectMapper.readValue(jsonString, PersonInject.class);
        System.out.println(pi.getResponseTime());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

9.@JsonCreator && @ConstructorProperties - 反序列化時採用的構造方法

@JsonCreator 用於在json數據反序列化到實例對象時採用哪個構造方法,同時搭配 @JsonProperty 註解用於相關屬性的。

package org.example;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class PersonCreator {
    private String name;

    private int age;

    // 構造方法1
    public PersonCreator(String name) {
        this.name = name;
    }

    // 構造方法2
    @JsonCreator // 用於反序列化時的處理
    public PersonCreator(@JsonProperty("username") String name,
                         @JsonProperty("age") int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Test{" +
                "name='" + name + ''' +
                ", age='" + age + ''' +
                '}';
    }

    public static void main(String[] args) throws Exception {
        String jsonString = "{"username": "Alice", "age": 18}"; // username -> name
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            PersonCreator pc = objectMapper.readValue(jsonString, PersonCreator.class);
            System.out.println(pc);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

@ConstructorProperties 也用於構造方法,但相比 @JsonCreator 的使用要簡單,可以認為 @ConstructorProperties = @JsonCreator + @JsonProperty

package org.example;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.beans.ConstructorProperties;

public class PersonConstructorProperties {
    private String username;

    private int age;

    public PersonConstructorProperties(String username) {
        this.username = username;
    }

    @ConstructorProperties({"name", "age"})
    public PersonConstructorProperties(String username, int age) {
        System.out.println("全參構造函數...");
        this.username = username;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Test{" +
                "username='" + username + ''' +
                ", age='" + age + ''' +
                '}';
    }

    public static void main(String[] args) {
        String jsonString = "{"name": "Bob", "age": 29}";
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            PersonConstructorProperties pcp = objectMapper.readValue(jsonString, PersonConstructorProperties.class);
            System.out.println(pcp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

10.@JsonSerialize && @JsonDeserialize - 自定義序列化方法

這兩個註解用於實現自定義的序列化和反序列化的處理,比如我們有個需求,需要將小數的某個欄位規定精確位數,為空時輸出空字元串。

@JsonSerialize

package org.example;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.IOException;
import java.math.RoundingMode;
import java.text.DecimalFormat;

public class PersonSerialize {
    @JsonSerialize(using = CustomDoubleSerialize.class, nullsUsing = NullNumberSerialize.class)
    private Double model;

    @JsonSerialize(nullsUsing = NullNumberSerialize.class)
    private Double business;

    private String name;

    public PersonSerialize() {
    }

    public Double getModel() {
        return model;
    }

    public void setModel(Double model) {
        this.model = model;
    }

    public Double getBusiness() {
        return business;
    }

    public void setBusiness(Double business) {
        this.business = business;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * Double保留4位小數,輸出string
 */
class CustomDoubleSerialize extends JsonSerializer<Double> {
    private static final DecimalFormat df = new DecimalFormat("#.####");

    @Override
    public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        df.setRoundingMode(RoundingMode.HALF_UP); // 4
        gen.writeString(df.format(value));
    }
}

/**
 * 任意類型null值,改為空字元串輸出
 */
class NullNumberSerialize extends JsonSerializer<Object> {

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString("");
    }
}

---
public static void jsonSerialize() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonSerialize ps = new PersonSerialize();
    ps.setName("Alice");
    ps.setModel(1.2345678);

    try {
        String jsonString = objectMapper.writeValueAsString(ps);
        System.out.println(jsonString); // {"model":"1.2346","business":"","name":"Alice"}
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

@JsonDeserialize

package org.example;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class PersonDeserialize {
    @JsonSerialize(using = LocalDatetimeSerialize.class)
    @JsonDeserialize(using = LocalDatetimeDeserialize.class)
    private LocalDateTime birthDate;

    private String name;

    public PersonDeserialize() {
    }

    public LocalDateTime getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDateTime birthDate) {
        this.birthDate = birthDate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class LocalDatetimeSerialize extends JsonSerializer<LocalDateTime> {
    static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);

    @Override
    public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        String str = value.format(DATE_FORMATTER);
        gen.writeString(str);
    }
}

class LocalDatetimeDeserialize extends JsonDeserializer<LocalDateTime> {
    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
        String str = p.getText();
        return LocalDateTime.parse(str, LocalDatetimeSerialize.DATE_FORMATTER);
    }
}
---
public static void jsonDeserialize() {
    ObjectMapper objectMapper = new ObjectMapper();
    PersonDeserialize pd = new PersonDeserialize();
    pd.setName("Dav");
    pd.setBirthDate(LocalDateTime.of(2000, 12, 5, 0, 0));

    String jsonString = null;

    // serialize
    try {
        jsonString = objectMapper.writeValueAsString(pd);
        System.out.println(jsonString); // {"birthDate":"2000年12月5日 00:00:00","name":"Dav"}
    } catch (Exception e) {
        e.printStackTrace();
    }

    // deserialize
    try {
        PersonDeserialize pd1 = objectMapper.readValue(jsonString, PersonDeserialize.class);
        // person -> name: Dav, birthdate: 2000-12-05T00:00
        System.out.printf("person -> name: %s, birthdate: %s\n", pd1.getName(), pd1.getBirthDate());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

11.@JsonAnyGetter && @JsonANySetter - 序列化對map欄位的處理

這兩個註解用於在序列化和反序列化時 map 結構的處理,具體說來:

  • @JsonAnyGetter,加在 getField() 上,用於序列化時將此map欄位的鍵值對移至json中的鍵值對
  • @JsonAnySetter,加在欄位上或者 setField() 都可以,加一個即可,用於反序列化時構造類實例,設置類實例屬性,將json中的非明確定義的鍵值對都設置到map結構的欄位中
package org.example;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;

import java.util.HashMap;
import java.util.Map;

public class PersonGetAndSet {
    private String username;

    private String pwd;

    private int age;

    // @JsonAnySetter // 加方法或者屬性都可以,但1個即可
    private Map<String, String> map;

    public PersonGetAndSet() {
        this.map = new HashMap<>();
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @JsonAnyGetter // serialize, {"username":"Ada","pwd":"123456","age":26,"key1":"val1","key2":"val2"}
    public Map<String, String> getMap() {
        return map;
    }

    @JsonAnySetter // deserialize, pwd: 123456, age: 26, map: {key1=val1, key2=val2}
    public void setMap(String key, String value) {
        this.map.put(key, value);
    }
}
---
public static void jsonGetterAndSetter() {
    PersonGetAndSet pgs = new PersonGetAndSet();
    pgs.setUsername("Ada");
    pgs.setAge(26);
    pgs.setPwd("123456");
    pgs.setMap("key1", "val1");
    pgs.setMap("key2", "val2");

    ObjectMapper objectMapper = new ObjectMapper();

    String jsonString = null;

    try {
        jsonString = objectMapper.writeValueAsString(pgs);
        System.out.println(jsonString);
    } catch (Exception e) {
        e.printStackTrace();
    }

    try {
        PersonGetAndSet pgs1 = objectMapper.readValue(jsonString, PersonGetAndSet.class);
        System.out.printf("person -> username: %s, pwd: %s, age: %d, map: %s\n", pgs1.getUsername(), pgs1.getPwd(), pgs1.getAge(), pgs1.getMap());
    } catch (Exception e) {
        e.printStackTrace();
    }
}
---

12.@JsonNaming - 序列化時輸出格式

@JsonNaming 加在類上,用以規範序列化時輸出的欄位鍵值的形式,主要有以下格式:

  • SnakeCaseStrategy, 蛇形體, 如 first_name
  • UpperCamelCaseStrategy, 大寫駝峰體,如 FirstName
  • LowerCaseStratey, 小寫連體,如 firstname
  • LowerDotCaseStratey, 小寫點分,如 first.name
package org.example;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;

//@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) // 蛇形體:{"first_name":"Matt","second_name":"Damon"}
//@JsonNaming(value = PropertyNamingStrategy.UpperCamelCaseStrategy.class)  // {"FirstName":"Matt","SecondName":"Damon"}
//@JsonNaming(value = PropertyNamingStrategy.LowerCaseStrategy.class)  // {"firstname":"Matt","secondname":"Damon"}
@JsonNaming(value = PropertyNamingStrategy.LowerDotCaseStrategy.class)  // {"first.name":"Matt","second.name":"Damon"}
public class PersonNaming {
    private String firstName;

    private String secondName;

    public PersonNaming() {
    }

    public PersonNaming(String firstName, String secondName) {
        this.firstName = firstName;
        this.secondName = secondName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSecondName() {
        return secondName;
    }

    public void setSecondName(String secondName) {
        this.secondName = secondName;
    }

    public static void main(String[] args) {
        PersonNaming pn = new PersonNaming();
        pn.setFirstName("Matt");
        pn.setSecondName("Damon");

        ObjectMapper objectMapper = new ObjectMapper();

        try {
            String jsonString = objectMapper.writeValueAsString(pn);
            System.out.println(jsonString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

13.staic 和 transient 欄位

如果欄位屬性中有這兩個修飾符,則在序列化處理時忽略相關欄位。

參考:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 每天,我們都在和各種文檔打交道,PRD、技術方案、個人筆記等等等。 其實文檔排版有很多學問,就像我,對排版有強迫症,見不得英文與中文之間不加空格。 所以,最近在做這麼一個谷歌擴展插件 chrome-extension-text-formatting,通過谷歌擴展,快速將選中文本,格式化為符合 中文文 ...
  • 從接觸領域驅動設計的初學階段,到實現一個舊系統改造到DDD模型,再到按DDD規範落地的3個的項目。對於領域驅動模型設計研發,從開始的各種疑惑到吸收各種先進的理念,目前在技術實施這一塊已經基本比較成熟。在既往經驗中總結了一些在開發中遇到的技術問題和解決方案進行分享。 ...
  • 目錄 事務的四大特性? 資料庫的三大範式 事務隔離級別有哪些? 生產環境資料庫一般用的什麼隔離級別呢? 編碼和字元集的關係 utf8和utf8mb4的區別 什麼是索引? 索引的優缺點? 索引的作用? 什麼情況下需要建索引? 什麼情況下不建索引? 索引的數據結構 Hash索引和B+樹索引的區別? 為什 ...
  • docker部署是主流的部署方式,極大的方便了開發部署環境,保持了環境的統一,也是實現自動化部署的前提。 1 項目的目錄結構 dist: 使用build打包命令,生成的打包目錄 npm run build : 打包項目命令 docker: 存放docker容器需要修改的配置目錄,比如 nginx配置 ...
  • 目錄0. 前言1. Collection介面1.1. List介面1.1.1. ArrayList1.1.2. LinkedList1.1.3. Vector1.1.4. Stack1.2. Set介面1.2.1. HashSet1.2.2. LinkedHashSet1.2.3. TreeSet1 ...
  • Python可以用於資料庫應用程式。 其中最流行的資料庫之一是MySQL。 MySQL資料庫 為了能夠在本教程中嘗試代碼示例,您應該在電腦上安裝MySQL。 您可以在 MySQL官方網站 下載MySQL資料庫。 安裝MySQL驅動程式 Python需要一個MySQL驅動程式來訪問MySQL資料庫。 ...
  • Go 介面:nil介面為什麼不等於nil? 本文主要內容:深入瞭解介面類型的運行時表示層。 目錄Go 介面:nil介面為什麼不等於nil?一、Go 介面的地位二、介面的靜態特性與動態特性2.1 介面的靜態特性與動態特性介紹2.2 “動靜皆備”的特性的好處三、nil error 值 != nil四、接 ...
  • 1、visio studio2019安裝及使用 1)下載地址:https://visualstudio.microsoft.com/zh-hans/vs/older-downloads/ 2)選擇社區版進行下載 3)安裝 環境:win10-X64 ①勾選使用C++桌面開發 ②除預設選項外,勾選適用於 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...