有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何读取具有可变数组深度和结构的复杂JSON字符串?

我有很多JSON数据,这些数据以嵌套列表的形式组织。每个列表由其他列表组成,这些列表可以包含其他列表,依此类推。最深的列表由一对经度和纬度组成,例如

[[[.....[16.353542354,48.2354242424],[16.46353535,48.2546754646]....].....].

它将如下图所示:

Coord list

我基本上不知道这些列表是如何嵌套的。它们总是不同的。下一个困难的部分是,我需要从中获得“坐标多边形”。这意味着仅由成对坐标组成的列表属于同一个多边形。例如:

[......[[16.23542424,48.2342424242],[16.2423242352354,48.12342534634],[16.35353453535,48.345635353]]......

这意味着有一个由3对坐标(3个角)组成的多边形。 我确信这可以通过某种字符串解析来解决。我想知道使用基本JSON是否可以做到这一点。简单(或任何其他API)的可能性。问题是JSON对它正在解析的数据一无所知。我必须告诉JSON对象是什么,并且必须使用类型转换来获得正确的数据。参见以下示例here。现在我需要另一种方法,但我永远不知道数据是什么类型的(“它是另一个列表还是数据是一对坐标”),因为这些列表是非常动态的。如何以方便的方式实现这一点?我可以编写一些带有“push-and-pop行为”的字符串解析算法来逐字符比较JSON字符串,但我想知道是否有更好的方法来做到这一点

[更新]
我发现这是一种标准化的JSON格式,称为GeoJSON。如果你知道如何读取数据,那就很清楚了。多多边形由多边形组成,多边形可以有孔,由多边形对象中的第二个数组表示。见规范: PolygonMultipolygon


共 (4) 个答案

  1. # 1 楼答案

    下面的代码将使用JSON Java library(jar可以从here下载)递归地将任何深度的纬度和经度值提取到resultantArray

    public void run() throws JSONException
    {
        JSONArray nestedList =
            new JSONArray("[" + "[ 1, 2 ]," + "[ [ 1, 2 ], [ 1, 2 ], [ 1, 2 ] ]," + "[ 3, 4 ],"
                + "[ [ [ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ] ], [ 1, 2 ], [ 1, 2 ], [ 1, 2 ] ] ] ]");
        parseLists(nestedList);
    }
    
    private void parseLists(JSONArray nestedList) throws JSONException
    {
        List<Location> resultantArray = new ArrayList<Location>();
        parseNestedList(nestedList, resultantArray);
        System.out.println(resultantArray.size());
    }
    
    private void parseNestedList(JSONArray json, List<Location> resultantArray) throws JSONException
    {
        int elementCount = json.length();
        if (elementCount <= 0)
        {
            return;
        }
        if (json.get(0) instanceof JSONArray)
        {
            for (int i = 0; i < elementCount; i++)
            {
                parseNestedList((JSONArray) json.get(i), resultantArray);
            }
        }
        else
        {
            resultantArray.add(new Location(Double.parseDouble(json.get(0).toString()), Double.parseDouble(json
                .get(1)
                .toString())));
        }
    }
    

    完成后,您应该运行算法来识别多边形,将resultantArray中的条目视为点

  2. # 2 楼答案

    这里有多个问题,所以我首先建议您将问题分解为多个步骤

    第1步,您需要以某种方式在嵌套中的某个地方找到一个不同的列表

    您没有提到您正在使用的编程语言,因此该问题的答案会有所不同。如果直接在JavaScript中执行此操作,则访问任何不同的列表都是一种简单的数据访问:

    geometry.coordinates[0][1]
    

    或者作为列表的Java映射(不检查空返回或无效数组索引的错误,仅举一个例子)

    geometry.get("coordinates").get(0).get(1)      
    

    如果你使用java或C++之类的东西,你可能会发现使用JSON库更容易,并将数据转换成语言适当的结构,例如向量映射。我不会试图直接操作JSON字符串

    然后,一旦您能够以适合语言的方式获取数据内容,第2步将是根据您的规则评估您检索的内容,并确定您检索的数据类型

  3. # 3 楼答案

    I basically don't know how nested those lists are

    您确切地知道这些列表嵌套得有多深。在json的顶部,您有:

    "type": "Multipolygon"
    

    对我来说,这意味着List<Polygon>。现在,什么是Polygon?嗯,这显然是一个List<Coordinate>。最后,我们知道Coordinate是一个包含两个元素的列表

    最后,我们有List<List<List<double>>>。阵列的深度是已知的

    class Location {
        private double _lat;
        private double _long;
    
        public Location(double lat, double long) { _lat = lat; _long = long }
    
        public static Location fromJSONArray(JSONArray json) {
            int n = json.length();
            if(n != 2) throw new IllegalArgumentException('json');
    
            return new Location(json.getDouble(0), json.getDouble(1));
        }
    }
    class Polygon : List<Location> {
        public static Polygon fromJSONArray(JSONArray json) {
            int n = json.length();
            Polygon p = new Polygon();
            for(int i = 0; i < n; i++) {
                p.add(Location.fromJSONArray(json.getJSONArray(i)));
            }
            return polygon;
        }
    }
    
    private List<Polygon> parseLists(JSONArray nestedList) throws JSONException
    {
        List<Polygon> polygons = new ArrayList<Polygon>();
        int n = json.length();
        for(int i = 0; i < n; i++) {
            polygons.add(Polygon.fromJSONArray(json.getJSONArray(i)));
        }
        return polygons;
    }
    
  4. # 4 楼答案

    您希望用什么语言解析JSON。从理论上讲,这个想法可以应用于大多数语言。如果是javascript,您可以使用它

      for(var key in myJSONObjectVariable){
           var current = myJSONObjectVariable[key];
           //Have some logic or inner loops taking place on current
      }
    

    不过,根据JSON数据的不可预测性,我认为您可能是对的。但是,字符串解析可能是一种方法