网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon)

如果一个对象太复杂了,那么在网络传输键的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 points = new ArrayList<>();
        points.add(point1);
        points.add(point2);
        points.add(point3);
        points.add(point4);

        List 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 list = new ArrayList<>();
        if(areaList == null ){
            return list;
        }
        /**
         * List listString = JSON.parseObject(areaList, new TypeReference>(){});
         * 注意这样写是错误的,Area包含属性GeoJsonPolygon,解析不了
         * 只好吧List的泛型写成String
         */
        List listString = JSON.parseObject(areaList, new TypeReference>(){});

        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 points = JSON.parseObject(pointsString, new TypeReference>() {});
            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 points = JSON.parseObject(pointsString, new TypeReference>() {}) 会报错,因为1.2.7要求这里的泛型类Point必须有无参构造函数,而1.2.47版本没有无参构造函数也可以。

 

总结

a. 服务B首先使用了@RequestBody注解,然后解析该嵌套数据类型;

b. 如果是list利用List<String> listString = JSON.parseObject(areaList, new TypeReference>(){}) 先解析成泛型为String的List。因为GeoJsonPolygon太复杂了,直接解析不了,如果是简单的如Point可以直接List points = JSON.parseObject(pointsString, new TypeReference>() {});

c. 如果不是list,并且该String对象还是嵌套JSON数据格式,就把String对象解析成JsonObject 对象;

d. 利用JsonObject 对象的getString方法获取对应属性key的字符串,如果该字符串还是复杂的JSON数据,进行b或c步骤,直到获取到想要的数据或解析完成。

 

 在线JSON:http://www.bejson.com/

 
  

转载于:https://www.cnblogs.com/theRhyme/p/9580046.html

你可能感兴趣的:(网络传输中利用fastjson将复杂嵌套数据类型Json格式转换(GeoJsonPolygon))