標籤:code 完成 1.2 問題 beans 通過 app gets tst
如果一個對象太複雜了,那麼在網路傳輸鍵的JSON格式資料轉換容易出問題。
比如下面一個類Area.java
import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;@Data@NoArgsConstructor@AllArgsConstructorpublic class Area { private String name; private GeoJsonPolygon geoJsonPolygon;}
在這個Area類中,有個屬性GeoJsonPloygon有點複雜,這個類的源碼我就不貼了,只給大家看一下Area對象中包含它的JSON格式資料表示:
{ "name": "AAAA", "geoJsonPolygon": { "points": [{ "x": 3.4, "y": 3.9 }, { "x": 6.2, "y": 8.1 }, { "x": 9.8, "y": 3.1 }, { "x": 3.4, "y": 3.9 }], "coordinates": [{ "type": "LineString", "coordinates": [{ "x": 3.4, "y": 3.9 }, { "x": 6.2, "y": 8.1 }, { "x": 9.8, "y": 3.1 }, { "x": 3.4, "y": 3.9 }] }], "type": "Polygon" }}
上面紅色標識就是GeoJsonPolygon的JSON格式。
這裡如果看不懂points和coordinates沒關係。
下面類比一個服務A向另一個服務B,傳輸泛型為Area的一個List,服務B解析該資料,並返回資料。
服務A的Controller,就是造一個泛型為Area的一個List,通過RestTemplate向B服務傳資料。
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.data.geo.Point;import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;import java.util.ArrayList;import java.util.List;@RestControllerpublic class SendController { @Autowired private RestTemplate restTemplate; @GetMapping(value = "/send") @ResponseBody public List sendArea(){ Point point1 = new Point(3.4, 3.9); Point point2 = new Point(6.2, 8.1); Point point3 = new Point(9.8, 3.1); Point point4 = new Point(3.4, 3.9); List<Point> points = new ArrayList<>(); points.add(point1); points.add(point2); points.add(point3); points.add(point4); List<Area> areaList = new ArrayList<>(); areaList.add(new Area("AAAA",new GeoJsonPolygon(points))); areaList.add(new Area("BBBB",new GeoJsonPolygon(points))); areaList.add(new Area("CCCC",new GeoJsonPolygon(points))); String url = ReceiveController.BASE_URL+ReceiveController.POST_MAPPING; ResponseEntity entity = restTemplate.postForEntity(url, areaList,List.class); List body = (List) entity.getBody(); return body; } @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }}
服務B的Controller
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.alibaba.fastjson.TypeReference;import org.springframework.data.geo.Point;import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;import java.util.List;@RestControllerpublic class ReceiveController { public static final String BASE_URL = "http://localhost:8080"; public static final String POST_MAPPING = "/receive"; @PostMapping(value = POST_MAPPING) @ResponseBody public List areaList(@RequestBody String areaList){ List<Area> list = new ArrayList<>(); if(areaList == null ){ return list; } /** * List<Area> listString = JSON.parseObject(areaList, new TypeReference<List<Area>>(){}); * 注意這樣寫是錯誤的,Area包含屬性GeoJsonPolygon,解析不了 * 只好吧List的泛型寫成String */ List<String> listString = JSON.parseObject(areaList, new TypeReference<List<String>>(){}); JSONObject jsonObject = null; JSONObject polygonJsonObject = null; GeoJsonPolygon geoJsonPolygon = null; for (int i=0; i < listString.size(); i++){ String s = listString.get(i); jsonObject = JSONObject.parseObject(s); //通過JSONObject對象擷取key對應的value String name = jsonObject.getString("name"); //解析複雜的GeoJsonPolygon屬性 String geoJsonPolygonString = jsonObject.getString("geoJsonPolygon"); polygonJsonObject = JSONObject.parseObject(geoJsonPolygonString); String pointsString = polygonJsonObject.getString("points"); List<Point> points = JSON.parseObject(pointsString, new TypeReference<List<Point>>() {}); geoJsonPolygon = new GeoJsonPolygon(points); Area area = new Area(); area.setName(name); area.setGeoJsonPolygon(geoJsonPolygon); list.add(area); } return list; }}
注意:使用的是fastjson版本是1.2.47,如果是1.2.7版本在執行這條語句List<Point> points = JSON.parseObject(pointsString, new TypeReference<List<Point>>() {}) 會報錯,因為1.2.7要求這裡的泛型類Point必須有無參建構函式,而1.2.47版本沒有無參建構函式也可以。
a. 服務B首先使用了@RequestBody註解,然後解析該嵌套資料類型;
b. 如果是list利用List<String> listString = JSON.parseObject(areaList, new TypeReference<List<String>>(){}) 先解析成泛型為String的List。因為GeoJsonPolygon太複雜了,直接解析不了,如果是簡單的如Point可以直接List<Point> points = JSON.parseObject(pointsString, new TypeReference<List<Point>>() {});
c. 如果不是list,並且該String對象還是嵌套JSON資料格式,就把String對象解析成JsonObject 對象;
d. 利用JsonObject 對象的getString方法擷取對應屬性key的字串,如果該字串還是複雜的JSON資料,進行b或c步驟,直到擷取到想要的資料或解析完成。
線上JSON:http://www.bejson.com/
網路傳輸中利用fastjson將複雜嵌套資料類型Json格式轉換(GeoJsonPolygon)