1. 程式人生 > >網絡傳輸中利用fastjson將復雜嵌套數據類型Json格式轉換(GeoJsonPolygon)

網絡傳輸中利用fastjson將復雜嵌套數據類型Json格式轉換(GeoJsonPolygon)

bsp ejs style post 數據表 strong 註意 ets beans

如果一個對象太復雜了,那麽在網絡傳輸鍵的JSON格式數據轉換容易出問題。

比如下面一個類Area.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;

@Data
@NoArgsConstructor
@AllArgsConstructor
public 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; @RestController public 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;

@RestController
public 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)