0

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

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

它看起来像这样的图表:

坐标列表

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

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

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

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

4

4 回答 4

2

我基本上不知道这些列表是如何嵌套的

您确切地知道这些列表的嵌套程度。在你的 json 的顶部,你有:

"type": "Multipolygon"

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

总而言之,我们有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;
}
于 2012-09-01T14:22:50.033 回答
0

用什么语言来解析 JSON。从理论上讲,这个想法可以适用于大多数语言。如果它的 javascript 你可以使用

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

然而,根据 JSON 数据的不可预测性,我认为您可能是对的。字符串解析可能是要走的路

于 2012-09-01T13:04:25.360 回答
0

您在这里有多个问题,因此我首先建议您将问题分解为多个步骤。

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

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

geometry.coordinates[0][1]

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

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

如果您使用 Java 或 C++ 或类似的东西,您可能会发现使用 JSON 库并将数据转换为适合语言的结构(例如矢量映射)更容易。我不会尝试直接操作 JSON 字符串。

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

于 2012-09-01T13:12:28.970 回答
0

下面的代码将递归提取任意深度的纬度和经度值resultantArray,使用JSON Java 库(jar 可以从这里下载):

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())));
    }
}

完成后,您应该运行算法来识别多边形,并考虑resultantArrayas 点中的条目。

于 2012-09-01T13:16:24.507 回答