<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      從 “JSON 字段適配噩夢(mèng)” 到 “Spring Boot 優(yōu)雅解決方案”,你只差這一篇

      在 Spring Boot 項(xiàng)目開(kāi)發(fā)中,前后端數(shù)據(jù)交互時(shí),JSON 數(shù)據(jù)格式憑借其簡(jiǎn)潔、高效的特性,成為了數(shù)據(jù)傳輸?shù)?“寵兒”。但在 Spring Boot 項(xiàng)目日常開(kāi)發(fā)中,一個(gè)讓無(wú)數(shù)開(kāi)發(fā)者頭疼不已的問(wèn)題常常出現(xiàn):前端傳來(lái)的 JSON 數(shù)據(jù)與后端 Java 類的屬性對(duì)不上號(hào) 。想象一下,你滿心歡喜地準(zhǔn)備接收前端發(fā)送的數(shù)據(jù),卻發(fā)現(xiàn)它們像是兩個(gè)世界的產(chǎn)物,無(wú)法完美契合。
      比如,前端提交的 JSON 數(shù)據(jù)可能是這樣的:

      {
          "name": "lybgeek",
          "mobile": "13800000000",
          "extFields": {
              "email": "lybgeek@163.com",
              "age": 18
          }
      }
      

      又或是這樣:

      {
          "name": "lybgeek",
          "mobile": "13800000000",
          "email": "lybgeek@163.com",
          "age": 18
      }
      

      而后端定義的 Java 類卻只有簡(jiǎn)單的這幾個(gè)屬性:

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
      
          private String name;
      
          private String mobile;
      }
      

      這種情況下,后端如何精準(zhǔn)地獲取 JSON 中的email和age字段呢?難道只能望 “數(shù)據(jù)” 興嘆,束手無(wú)策?當(dāng)然不是!今天,就為大家?guī)?lái)一場(chǎng)知識(shí)盛宴,詳細(xì)剖析多種實(shí)用到爆的解決方案,讓你輕松攻克這一難題,代碼寫(xiě)得更絲滑,開(kāi)發(fā)效率直線上升!

      場(chǎng)景痛點(diǎn)剖析:為什么 JSON 字段匹配問(wèn)題如此棘手?

      在微服務(wù)架構(gòu)盛行的當(dāng)下,前后端分離開(kāi)發(fā)模式成為主流。前端開(kāi)發(fā)人員按照業(yè)務(wù)需求構(gòu)建靈活的數(shù)據(jù)結(jié)構(gòu),而后端開(kāi)發(fā)人員則依據(jù)自身的業(yè)務(wù)邏輯定義 Java 實(shí)體類。這就導(dǎo)致了在數(shù)據(jù)交互的過(guò)程中,出現(xiàn) JSON 字段與 Java 類屬性不匹配的情況。這種不匹配不僅增加了開(kāi)發(fā)的復(fù)雜度,還可能引發(fā)數(shù)據(jù)解析錯(cuò)誤、類型轉(zhuǎn)換異常等問(wèn)題,嚴(yán)重影響項(xiàng)目的穩(wěn)定性和開(kāi)發(fā)進(jìn)度。

      實(shí)戰(zhàn)演練:獲取 JSON 中 “多余字段” 的 N 種姿勢(shì)

      方法一:巧用 Map,輕松接招

      通過(guò)定義一個(gè)Map對(duì)象來(lái)接收和處理這些額外字段,簡(jiǎn)單又直接,就像是給你的數(shù)據(jù)處理工具箱里添加了一把萬(wàn)能扳手,輕松應(yīng)對(duì)各種不匹配情況。

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
          private String name;
          private String mobile;
          protected Map<String,Object> extFields;
      }
      
      

      測(cè)試代碼如下:

       @PostMapping("json-map")
      public User getUser(@RequestBody User user){
          UserUtil.print(user,"email","age");
          return user;
      }
      

      打印工具類:

      public final class UserUtil {
      
          private UserUtil() {
          }
      
      
          public static void print(User user String...key){
              System.out.println("name:" + user .getName());
              System.out.println("mobile:" + user .getMobile());
      
              if(ArrayUtil.isNotEmpty(key)){
                  for (String k : key) {
                          System.out.println(k + ":" + user.getExtFields().get(k));
                      }
              }
          }
          }
      

      單元測(cè)試:

       @Test
          @DisplayName("測(cè)試-通過(guò)Map處理JSON對(duì)象中未被Java類中屬性映射的字段")
          public void testJsonMap() throws Exception{
             
              String json = """
      		{
      		    "name": "lybgeek",
      		    "mobile": "13800000000",
      		    "extFields": {
      		        "email": "lybgeek@163.com",
      		        "age": 18
      		    }
      		}
      		"""
      
              MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/json-map")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(json)
              ).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
      
      
          }
      
      

      控制臺(tái)輸出:

      name:lybgeek
      mobile:13800000000
      email:lybgeek@163.com
      age:18
      

      優(yōu)勢(shì): 實(shí)現(xiàn)簡(jiǎn)單,無(wú)需引入額外的依賴,對(duì)于臨時(shí)處理少量額外字段非常方便。
      局限: 在復(fù)雜的業(yè)務(wù)場(chǎng)景下,對(duì)Map的操作可能會(huì)使代碼變得不夠直觀,難以維護(hù)。

      方法二:借助 JsonNode,精準(zhǔn)出擊

      引入 Jackson 庫(kù),使用JsonNode來(lái)處理,就如同給你的數(shù)據(jù)處理裝上了高精度的瞄準(zhǔn)鏡,精準(zhǔn)定位并提取所需字段。

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
      
          private String name;
          private String mobile;
          private JsonNode extFields;
      }
      
      

      測(cè)試代碼:

       @PostMapping("json-node")
          public User getUser(@RequestBody User user){
              UserUtil.print(user,"email","age");
              return user;
      
          }
      

      單元測(cè)試:

       @Test
          @DisplayName("測(cè)試-通過(guò)JsonNode處理JSON對(duì)象中未被Java類中屬性映射的字段")
          public void testJsonNode() throws Exception{
               String json = """
      		{
      		    "name": "lybgeek",
      		    "mobile": "13800000000",
      		    "extFields": {
      		        "email": "lybgeek@163.com",
      		        "age": 18
      		    }
      		}
      		"""
      
              MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/json-node")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(json)
              ).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
      
              
      
            
      
          }
      
      

      控制臺(tái)輸出:

      name:lybgeek
      mobile:13800000000
      email:lybgeek@163.com
      age:18
      

      優(yōu)勢(shì): 提供了靈活的 JSON 節(jié)點(diǎn)訪問(wèn)方式,能夠處理復(fù)雜的 JSON 結(jié)構(gòu),對(duì)于嵌套的 JSON 數(shù)據(jù)處理得心應(yīng)手。
      局限: 需要對(duì) Jackson 庫(kù)有一定的了解,并且代碼中對(duì)JsonNode的操作較多時(shí),會(huì)增加代碼的復(fù)雜性。

      方法三:@JsonAnySetter 與 @JsonAnyGetter 雙劍合璧

      • @JsonAnySetter 是 Jackson 庫(kù)中的一個(gè)注解,用于處理 JSON 對(duì)象中未被 Java 類中屬性映射的字段,當(dāng) JSON 數(shù)據(jù)包含不匹配類中定義的屬性時(shí),使用此注解的方法會(huì)接收這些額外的鍵值對(duì)。
      • @JsonAnyGetter 注解用于標(biāo)記一個(gè)返回 Map<String, Object> 類型的方法,Jackson 在將 Java 對(duì)象序列化為 JSON 時(shí),會(huì)將該方法返回的 Map 中的鍵值對(duì)添加到生成的 JSON 對(duì)象中,這樣可以在不預(yù)先定義所有屬性的情況下,動(dòng)態(tài)地向 JSON 中添加屬性。

      使用 Jackson 庫(kù)的@JsonAnySetter和@JsonAnyGetter注解,實(shí)現(xiàn)動(dòng)態(tài)處理,就像給你的數(shù)據(jù)處理賦予了超能力,能夠自動(dòng)適應(yīng)各種變化。

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
      
          private String name;
          private String mobile;
          protected Map<String,Object> extFields;
      
           @JsonAnySetter
          public void addFields(String key,Object value){
              if(MapUtil.isEmpty(extFields)){
                  extFields = new HashMap<>();
              }
              extFields.put(key,value);
          }
      
       @JsonAnyGetter
          public Map<String,Object> getExtFields(){
              return extFields;
          }
      }
      
      

      測(cè)試代碼:

       @PostMapping("json-any-setter")
          public User getUser(@RequestBody User user){
              UserUtil.print(user,"email","age");
              return user;
      
          }
      

      單元測(cè)試:

        @Test
          @DisplayName("測(cè)試-通過(guò)@JsonAnySetter處理JSON對(duì)象中未被Java類中屬性映射的字段")
          public void testJsonAnySetter() throws Exception{
      
       String json = """
      		{
          "name": "lybgeek",
          "mobile": "13800000000",
          "email": "lybgeek@163.com",
          "age": 18
      	}
      		"""
      
              MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/json-any-setter")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(json)
              ).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
      
              System.out.println(mvcResult.getResponse().getContentAsString());
      
          }
      

      控制臺(tái)輸出:

      name:lybgeek
      mobile:13800000000
      email:lybgeek@163.com
      age:18
      {"name":"lybgeek","mobile":"13800000000","email":"lybgeek@163.com","age":18}
      

      優(yōu)勢(shì): 在 Java 類中無(wú)需預(yù)先定義所有屬性,能夠動(dòng)態(tài)地處理 JSON 中的額外字段,代碼簡(jiǎn)潔且易于理解。
      局限: 主要適用于處理簡(jiǎn)單的鍵值對(duì)形式的額外字段,如果 JSON 結(jié)構(gòu)復(fù)雜,可能需要額外的處理邏輯。

      方法四:自定義序列化與反序列化,深度定制

      通過(guò)@JsonDeserialize和@JsonSerialize注解結(jié)合自定義序列化和反序列化類,實(shí)現(xiàn)更靈活的處理,就像是為你的數(shù)據(jù)處理量身定制一套專屬的 “戰(zhàn)甲”,無(wú)往而不利。

      自定義反序列化類:

      public class UserJsonDeserializer extends JsonDeserializer<User> {
      
          @Override
          public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
              JsonNode jsonNode = p.getCodec().readTree(p);
              // 獲取JSON對(duì)象中未被User類中屬性映射的字段
              Map<String,Object> extFields = new HashMap<>();
              addFields(extFields,jsonNode,"email","age");
      
              User user = new User();
              user.setExtFields(extFields);
              user.setName(getValue(jsonNode,"name"));
              user.setMobile(getValue(jsonNode,"mobile"));
      
              return user;
          }
      
      public String getValue(JsonNode jsonNode, String key){
              if(jsonNode.has(key)){
                  return jsonNode.get(key).asText();
              }
              return null;
          }
      
          public void addFields(Map<String,Object> extFields, JsonNode jsonNode, String...key){
              for(String k : key){
                  if(jsonNode.has(k)){
                      extFields.put(k,getValue(jsonNode,k));
                  }
              }
          }
      
      

      自定義序列化類:

      public class UserJsonSerializer extends JsonSerializer<User> {
          @Override
          public void serialize(User value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              Map<String,Object> userMap = new HashMap<>();
              userMap.put("name",value.getName());
              userMap.put("mobile",value.getMobile());
              if(MapUtil.isNotEmpty(value.getExtFields())){
                  userMap.putAll(value.getExtFields());
              }
      
              gen.writeObject(userMap);
          }
      }
      

      在實(shí)體類上添加注解:

      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @JsonDeserialize(using = UserJsonDeserializer.class)
      @JsonSerialize(using = UserJsonSerializer.class)
      public class User {
      
          private String name;
          private String mobile;
          protected Map<String,Object> extFields;
      }
      
      

      測(cè)試代碼:

       @PostMapping("json-deserializer")
          public User getUser(@RequestBody User user){
              UserUtil.print(user,"email","age");
              return user;
      
          }
      

      單元測(cè)試:

        @Test
           @DisplayName("測(cè)試-通過(guò)自定義反序列化+@JsonDeserialize處理JSON對(duì)象中未被Java類中屬性映射的字段")
          public void testJsonDeserializer() throws Exception{
      
       String json = """
      		{
          "name": "lybgeek",
          "mobile": "13800000000",
          "email": "lybgeek@163.com",
          "age": 18
      	}
      		"""
      
              MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/json-deserializer")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(json)
              ).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
      
              System.out.println(mvcResult.getResponse().getContentAsString());
      
          }
      

      控制臺(tái)輸出:

      name:lybgeek
      mobile:13800000000
      email:lybgeek@163.com
      age:18
      {"name":"lybgeek","mobile":"13800000000","email":"lybgeek@163.com","age":18}
      

      優(yōu)勢(shì): 能夠根據(jù)具體業(yè)務(wù)需求,對(duì) JSON 數(shù)據(jù)的序列化和反序列化過(guò)程進(jìn)行全面的控制,適用于復(fù)雜的業(yè)務(wù)場(chǎng)景。
      局限: 開(kāi)發(fā)成本較高,需要編寫(xiě)較多的代碼,并且對(duì)開(kāi)發(fā)者對(duì) Jackson 庫(kù)的理解要求較高。

      方法五:@JsonComponent,全局掌控

      使用@JsonComponent注解,將自定義的序列化器和反序列化器注冊(cè)到 Jackson 的ObjectMapper中,實(shí)現(xiàn)全局統(tǒng)一處理,就像是給整個(gè)數(shù)據(jù)處理流程安排了一位 “大管家”,一切井井有條。

      @JsonComponent
      public class UserJsonComponent {
      
         public static class UserJsonDeserializer extends JsonDeserializer<User> {
      
          @Override
          public User deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
              JsonNode jsonNode = p.getCodec().readTree(p);
              // 獲取JSON對(duì)象中未被User類中屬性映射的字段
              Map<String,Object> extFields = new HashMap<>();
              addFields(extFields,jsonNode,"email","age");
      
              User user = new User();
              user.setExtFields(extFields);
              user.setName(getValue(jsonNode,"name"));
              user.setMobile(getValue(jsonNode,"mobile"));
      
              return user;
          }
      
      public String getValue(JsonNode jsonNode, String key){
              if(jsonNode.has(key)){
                  return jsonNode.get(key).asText();
              }
              return null;
          }
      
          public void addFields(Map<String,Object> extFields, JsonNode jsonNode, String...key){
              for(String k : key){
                  if(jsonNode.has(k)){
                      extFields.put(k,getValue(jsonNode,k));
                  }
              }
          }
      
      public static class UserJsonSerializer extends JsonSerializer<User> {
          @Override
          public void serialize(User value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              Map<String,Object> userMap = new HashMap<>();
              userMap.put("name",value.getName());
              userMap.put("mobile",value.getMobile());
              if(MapUtil.isNotEmpty(value.getExtFields())){
                  userMap.putAll(value.getExtFields());
              }
      
              gen.writeObject(userMap);
          }
      }
      
      

      注: 通常情況下,序列化器和反序列化器類會(huì)定義為使用 @JsonComponent 注解的類的靜態(tài)內(nèi)部類。因?yàn)榉庆o態(tài)內(nèi)部類依賴于外部類的實(shí)例, 而在 Jackson 序列化和反序列化過(guò)程中,不會(huì)創(chuàng)建外部類的實(shí)例來(lái)調(diào)用非靜態(tài)內(nèi)部類的方法,所以必須使用靜態(tài)內(nèi)部類。

      測(cè)試代碼:

       @PostMapping("json-component")
          public User getUser(@RequestBody User user){
              UserUtil.print(user,"email","age");
              return user;
      
          }
      

      單元測(cè)試:

        @Test
             @DisplayName("通過(guò)自定義反序列化+@UserJsonComponent全局處理JSON對(duì)象中未被Java類中屬性映射的字段-單元測(cè)試")
          public void testJsonComponent() throws Exception{
      
       String json = """
      		{
          "name": "lybgeek",
          "mobile": "13800000000",
          "email": "lybgeek@163.com",
          "age": 18
      	}
      		"""
      
              MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/user/json-component")
                      .contentType(MediaType.APPLICATION_JSON_UTF8)
                      .content(json)
              ).andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
      
              System.out.println(mvcResult.getResponse().getContentAsString());
      
          }
      

      控制臺(tái)輸出:

      name:lybgeek
      mobile:13800000000
      email:lybgeek@163.com
      age:18
      {"name":"lybgeek","mobile":"13800000000","email":"lybgeek@163.com","age":18}
      

      優(yōu)勢(shì): 實(shí)現(xiàn)了全局的統(tǒng)一配置,無(wú)需在每個(gè)實(shí)體類上分別添加注解,便于維護(hù)和管理。
      局限: 如果項(xiàng)目中存在多個(gè)不同的 JSON 處理需求,可能會(huì)導(dǎo)致@JsonComponent注解的類變得過(guò)于龐大和復(fù)雜。

      總結(jié)

      本文詳細(xì)介紹了在 Spring Boot 項(xiàng)目中處理 JSON 對(duì)象中未被 Java 類屬性映射字段的多種方法,本質(zhì)上都是圍繞 JSON 與對(duì)象之間的序列化和反序列化展開(kāi)。每種方法都有其獨(dú)特的優(yōu)勢(shì)和適用場(chǎng)景,希望大家在實(shí)際開(kāi)發(fā)中能夠根據(jù)具體需求靈活選擇。

      福利:一鍵獲取完整代碼

      為了方便大家學(xué)習(xí)和實(shí)踐,我已經(jīng)將完整的示例代碼上傳至 GitHub,點(diǎn)擊下方鏈接即可獲?。?br> https://github.com/lyb-geek/springboot-learning/tree/master/springboot-dynamics-json
      覺(jué)得文章有用的話,別忘了點(diǎn)贊、分享和訂閱哦!你的支持是我創(chuàng)作的最大動(dòng)力!如果在實(shí)踐過(guò)程中有任何問(wèn)題,歡迎在評(píng)論區(qū)留言,我們一起探討。

      posted @ 2025-08-12 09:14  Linyb極客之路  閱讀(65)  評(píng)論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 亚洲熟妇色xxxxx欧美老妇| 国产精品v片在线观看不卡| 日本高清成本人视频一区| 国产精品国产三级国快看| 潮喷失禁大喷水无码| 无线乱码一二三区免费看| 成人午夜激情在线观看 | 仪陇县| 日本一区二区三区视频版| 亚洲尤码不卡av麻豆| 中文区中文字幕免费看| 久久成人伊人欧洲精品| 在线中文字幕国产一区| 艳妇臀荡乳欲伦交换h在线观看| 亚洲精品自产拍在线观看动漫 | 四虎精品视频永久免费| 久久久久久无码午夜精品直播| 亚洲老女人区一区二视频| 国产稚嫩高中生呻吟激情在线视频 | 99热精品毛片全部国产无缓冲| 漠河县| 最近中文国语字幕在线播放| 成人无码视频97免费| 国产精品中文av专线| 亚洲色成人网站www永久四虎| 日本高清中文字幕一区二区三区| 一区二区中文字幕av| 国产精品伊人久久综合网| 久久久无码精品国产一区| 国产成人理论在线视频观看| 九九在线精品国产| 精品人妻日韩中文字幕| 国产一区二区三区无遮挡| 亚洲另类激情专区小说婷婷久| 国产日韩AV免费无码一区二区三区| 国内揄拍国内精品人妻久久| 无码人妻黑人中文字幕| 日韩区中文字幕在线观看| 国产精品天干天干综合网| 欧美大屁股xxxx高跟欧美黑人| 国产精品男女午夜福利片|