• 网络传输中利用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<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/

    
    
  • 相关阅读:
    zookeeper分布式锁
    zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。
    理解分布式系统
    zookeeper
    Codeforces Round #261 (Div. 2)[ABCDE]
    L脚本语言语法手冊 0.10版
    [Lua]mac 上安装lua
    extjs 按条件查询出的数据在grid上不显示
    木桶效应
    Shuttle ESB(四)——公布订阅模式实例介绍(1)
  • 原文地址:https://www.cnblogs.com/theRhyme/p/9580046.html
Copyright © 2020-2023  润新知