关于@JsonProperty

前情摘要

先来一点故事补充,话说小明的领导给小明安排了一个任务,很简单就是调用别人的API,我们作为Client接收数据并进行相应的处理,领导说由于各种原因,目前不知道对方接口的返回数据格式,所以你先做数据解析吧,先写XML格式的,于是小明开始着手工作了,经过编码,调试,并且领导也review通过了。但是,领导接到消息说数据格式好像是JSON格式的,小明只好重新开始工作了。解析XML格式的代码请点击访问以下链接:

解析XML格式代码

代码编写之JSONObject解决一切

小明一听解析JSON格式,那不是手到擒来么,以前经常这么干,如以下代码所示

         JSONObject jsonObject = new JSONObject(assetJson);
         JSONArray jsonArray = jsonObject.getJSONArray("value");
         for(int i=0;i<jsonArray.length();i++) {
            JSONObject jsonObj = jsonArray.getJSONObject(i);
	    if(jsonObj.has("AssetNumber") && !jsonObj.isNull("AssetNumber")) {
               asset.setAssetNumber(jsonObj.getLong("AssetNumber"));
            }

这段代码应该都能读懂,就是传进来一个Json字符串,然后用一个实体类接收,为了防止异常保证代码健壮性,很多人都会像小明一样加上jsonObject.has(key)和jsonObject.isNull(key)。这时候小明正在为自己的小聪明得意,但是殊不知,这个json对象中有60多个key,意思就是得为这个小聪明多写120行重复的代码。然后再仔细一看,对方的API返回的数据,字段都是超级多,很显然,这么多重复代码无论你是放在Service层处理还是直接裸在Controller里都不是很友好。然后你是不是以为我要提高代码的可重用性,哈哈,这样的代码如果按这个思路来的话是没有办法简化的。那怎么办,换一个思路咯。(有点小啰嗦,请见谅)

代码编写之Json反序列化

小明想了想,现在整体项目使用的是spring boot,spring boot里集成了restTemplate,客户端根据自己的需要可以重写这里关于restTemplate的就不在赘述了。看到一篇关于HttpMessageConverter的文章,希望在你重写restTemplate的时候能帮助你完成关于消息类型转换的工作。如下:

https://segmentfault.com/a/1190000012659486

长话短说,封装好自己的restTemplate。小明想着使用实体类直接去接收服务端传过来的Json数据,代码如下:

 public ResponseEntity<JsonResultForMaterial> getMaterials() {
      return this.restTemplate.exchange( getNlyteServiceEndpoint()+ GetMaterialsURL, HttpMethod.GET,
            getDefaultEntity(), JsonResultForMaterial.class);
   }

 

json数据例子如下:

{"@odata.context": "/$metadata#Materials",
  "value": [{
    "@odata.type": "#Nlyte.Model.StandardNetworkMaterial",
    "MaterialID": 1
  },
  {
    "@odata.type": "#Nlyte.Model.StandardServerMaterial",
    "MaterialID": 96
  },
  {
    "@odata.type": "#Nlyte.Model.BladeServerMaterial",
    "MaterialID": 101
  }],
  "@odata.nextLink": "Materials?$skip=200"
}

 

由于服务端传过来的json数据格式问题,小明写了如下实体类

 



import java.util.List;

import com.fasterxml.jackson.annotation.JsonProperty;

public class JsonResultForMaterial {

   @JsonProperty(value="@odata.context")
   private String  odatacontext;
   
   private List<Material> value;
   
   @JsonProperty(value="@odata.nextLink")
   private String odatanextLink;

   public String getOdatacontext() {
      return odatacontext;
   }

   public void setOdatacontext(String odatacontext) {
      this.odatacontext = odatacontext;
   }

   public String getOdatanextLink() {
      return odatanextLink;
   }

   public void setOdatanextLink(String odatanextLink) {
      this.odatanextLink = odatanextLink;
   }

   public List<Material> getValue() {
      return value;
   }

   public void setValue(List<Material> value) {
      this.value = value;
   }
   
}
package com.vmware.wormhole.nlyteworker.model;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Material {

   @JsonProperty(value = "@odata.type")
   private String odataType;
   @JsonProperty(value = "MaterialID")
   private int materialID;
  
   public String getOdataType() {
      return odataType;
   }
   public void setOdataType(String odataType) {
      this.odataType = odataType;
   }
   public int getMaterialID() {
      return materialID;
   }
   public void setMaterialID(int materialID) {
      this.materialID = materialID;
   }
}

在Json反序列化过程中,key需要和你定义的实体类的属性对应,但是大家都知道,实体类属性的命名规范,关于首字母和特殊字符的问题是很严格的。以上json数据中出现了,这样的key如:

@odata.context 、MaterialID

这样是无法直接用实体类接收的。这时候需要用到@JsonProperty(),来修饰具体属性,这样就可以解决无法映射的问题。

这样我们就获得了一个json结果对象,里面有我们需要操作的属性。这里不用考虑,开篇的那个问题,比如key是否存在,key的值是否为空。然后代码可以改成如下:

  public List<Asset> getAssetsFromNlyte(List<NlyteAsset> nlyteAssets) {
      List<Asset> assetsFromNlyte = new ArrayList<Asset>();
      Asset asset;
      for(NlyteAsset nlyteAsset:nlyteAssets) {
         asset = new Asset();
         asset.setAssetNumber(nlyteAsset.getAssetNumber());
         asset.setTag(nlyteAsset.getTag());
         assetsFromNlyte.add(asset);
      }
      return assetsFromNlyte;
   }

这里其实是和开篇的代码做的事情是一样的,不同的是,开篇的代码接收到的是一个json字符串,需要使用JSONObject和JSONArray等进行处理,还需要判断key等等,最后再进行数据的封装。这里的代码直接接收到一个list,然后直接进行遍历,封装数据。这里就解决了,要写很多has(key)和isNull(key)判断的问题。

文章纯手打,如有啰嗦之处还请喷轻点,有些代码封装的比较深如有不明白可以多交流,如有不足还请多多指教。

最后当次王婆卖波瓜,新项目FlowGate求star,欢迎交流和贡献,正在和linux 基金会谈,不久就会贡献到linux 基金会,目前是在公司下面开源
项目地址:https://github.com/vmware/flowgate
项目中文简介:https://mp.weixin.qq.com/s/8w7QImwns-WTI0_Hf6sblg

下一篇更新关于:@JsonProperty,@NotNull,@JsonIgnore的具体实例使用,和其中发现的一些问题。
 

 

 

 

 

 

 

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值